【发布时间】:2020-09-14 08:07:36
【问题描述】:
假设我想在一些更高级别的算法的过程中处理某个类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 将不会被处理,反之亦然。
与equals() 一起使用的HashMap treated 会更适合我的问题吗?
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:我见过 cmets 关于使用“完美哈希码”,即为每个唯一对象分配唯一值的哈希码,因此无法为不同对象获得相似的哈希码。我不认为这是一个解决方案,因为(理论上)我可以处理任意数量的不同对象,而哈希码是 int 类型,这有效地限制了不同哈希码的数量。
【问题讨论】:
-
“与一些 equals() 一起使用的 HashMap 是否会更适合我的问题?” -> 您应该同时覆盖
.equals和 @无论如何,987654340@。而且“为每个唯一对象分配唯一值的哈希码”似乎与哈希码的观点不一致。 -
您似乎假设
HashSetonly 会查看哈希码。它没有。来自HashSet.contains的文档:“更正式地说,当且仅当此集合包含一个元素 e 满足 Objects.equals(o, e) 时才返回 true。” -
@JonSkeet 由于
HashSets 中没有get 方法,我假设HashSets 不存储对象,只存储它们的哈希码,这意味着contains方法只比较哈希码。显然我假设错了!所以如果我没记错的话,这解决了我的问题,我可以简单地使用HashSet。如果您愿意,可以发布该答案。 -
@J.Schmidt:没有
get方法,因为没有任何一种键或索引来获取单个值by - 但它仍然是一个集合......你可以迭代它等等。 -
@J.Schmidt:可能,但它不存在(我发现这有时很烦人,因为我想保留一个一组“规范”值)并且实际上并不是正常“设置”操作的一部分。它不是集合所固有的,就像 List 和 Map 的“按索引获取”或“按键获取”一样。
标签: java arraylist equals hashset hashcode