【问题标题】:How to avoid unchecked cast warning when cloning a HashSet?克隆 HashSet 时如何避免未经检查的强制转换警告?
【发布时间】:2012-03-04 09:35:03
【问题描述】:

我正在尝试制作一个名为 myHash 的点的 HashSet 的浅表副本。截至目前,我有以下几点:

HashSet<Point> myNewHash = (HashSet<Point>) myHash.clone();

然而,这段代码给了我一个未经检查的强制转换警告。有没有更好的方法来做到这一点?

【问题讨论】:

标签: java clone hashset


【解决方案1】:

另一个答案建议使用new HashSet&lt;Point&gt;(myHash)。但是,clone() 的意图是获取相同类型的新对象。如果myHashHashSet 的子类的实例,则使用new HashSet&lt;Point&gt;(myHash) 将丢失由子类添加的任何附加行为。

未经检查的强制转换警告只是一个警告。在许多情况下强制转换是安全的,但编译器不够聪明,无法确定它是安全的。但是,您可以将警告隔离到可以使用@SuppressWarnings("unchecked") 注释的单个方法中:

@SuppressWarnings("unchecked")
static <T implements Cloneable> clone(T o) { return (T)(o.clone()); }

【讨论】:

    【解决方案2】:

    你可以试试这个:

    HashSet<Point> myNewHash = new HashSet<Point>(myHash);
    

    【讨论】:

    • @TedHopp:完美。谢谢。
    • 然而这段代码等于addAll(myHash),因此它会遍历集合并手动添加每个元素,而clone() 使用包私有方法@987654324 更快地重建底层地图@ ... sigh 这正是我多年前编写自己的 HashMap/HashSet 的原因,而这正是今天存在如此多 Collection 替代品的原因...
    • @vaxquis - 是的,Oracle 对此构造函数的实现只是创建了一个空的HashSet,然后调用addAll。使用构造函数和手动调用addAll 之间的唯一区别是可读性,并且构造函数将容量计算打包以实现所需的负载因子 0.75。你有任何关于你的方法与股票构造函数的性能数据吗?
    • @TedHopp 是的,我的解析器引擎遇到了瓶颈,归结为 HashMap 效率。将基于 HashMap 的 HashSet 替换为真实的(不存储值,仅存储键),将两者都替换为定制版本,例如不安全的迭代器,提供它们的real 不可变版本(对数据进行预计算,可能是因为使用了构建器模式),并通过 System.arraycopy() 进行集合/映射复制。获得了 20% 的性能提升,这对我来说已经足够了。另外,附带说明一下,Microsoft/C# 使用更高的负载因子,最高可达 1.0,对于某些数据集来说它要好得多。
    • @vaxquis - 20% 的性能提升是巨大的;做得好。出于某种原因,Java 团队决定将 75% 的负载因子作为规范的一部分。他们确实提供了一个允许控制新HashSet 的负载因子的两个参数的构造函数。使用clone() 将保留对原始集(好或坏)有效的任何加载因子。
    猜你喜欢
    • 2012-03-18
    • 1970-01-01
    • 1970-01-01
    • 2010-10-05
    • 1970-01-01
    • 2015-05-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多