说我想用某种方法Object
在某些高级算法的过程中处理treat(Object o)
类的多个对象。在这种算法中,可能会出现相同的对象(没有相同的地址),因此我不想对待这些相同的对象中的每个对象,只出现第一个,而忽略其他对象。
一个简单的解决方案是实现ArrayList
结构以存储所有名为treated
的已处理对象,并执行以下操作。
if (!treated.contains(o)){
treat(o);
treated.add(o);
}
但是,我认为contains
方法在线性时间内运行,而使用HashSet
而不是ArrayList
可以在恒定时间内进行。
尽管这是我的问题:相同的哈希码不能确保相等性。换句话说,使用HashSet treated
如下:
if (!treated.contains(o)){
treat(o);
treated.add(o);
}
可能不会对待所有不同的对象,因为某些对象o1
最终可能具有与其他对象o2
相同的哈希码。如果o1
被处理,则o2
将不被处理,反之亦然。与HashMap treated
一起使用的equals()
是否更适合我的问题?
if (treated.containsKey(o.hashCode())){
Object o2 = treated.get(o.hashCode());
if (!o.equals(o2)){
treat(o);
}
} else {
treat(o);
treated.put(o.hashCode(), o);
}
推荐用于解决此问题的方法是什么?
NB:我已经看到有关使用“完美哈希码”的评论,即为每个唯一对象分配唯一值的哈希码,因此无法为不同对象获得类似的哈希码。我不认为这是解决方案,因为(从理论上来说)我可以处理任意数量的不同对象,而哈希码的类型为int
,有效地限制了不同哈希码的数量。
换句话说,如下使用
HashSet treated
[...]可能不会对待所有不同的对象,因为某些对象o1可能最终具有相同的对象哈希码作为另一个对象o2
这是基于错误的假设,即HashSet.contains
仅检查哈希码。并非如此-它使用哈希码来找到相等的candidates,但是然后像往常一样使用equals
检查实际的相等性。
从contains
method documentation:
如果此集合包含指定的元素,则返回true。更正式地讲,当且仅当此集合包含元素e使得
contains
时,才返回true。