为什么具有相同数据的两个不同的hashset具有相同的HashCode?



我最近在leetcode上遇到了一个问题,我用嵌套哈希集解决了这个问题。这就是问题所在,如果你感兴趣的话:https://leetcode.com/problems/group-anagrams/.

我的直觉是把每个单词的所有字母加到一个哈希集中,然后把这个哈希集中到另一个哈希集中。在每次迭代中,我将检查哈希集是否已经存在,如果存在,则添加到现有的哈希集。

奇怪的是,这似乎有效。为什么两个哈希集共享相同的哈希码,如果他们是不同的对象?像if(set1.hashCode() == set2.hashCode()) doStuff()这样的代码是有效的吗?

这是预期的。HashSet扩展了AbstractSet。AbstractSet中的hashCode()方法表示:

返回该集合的哈希码值。集合的哈希码被定义为集合中所有元素哈希码的和,其中空元素的哈希码被定义为零。这确保了s1.equals(s2)意味着s1. hashcode ()==s2. hashcode()对于任意两个集合s1和s2,如Object.hashCode的一般契约所要求的。

此实现遍历集合,对集合中的每个元素调用hashCode方法,并将结果相加。

下面是AbstractSet的代码:

public int hashCode() {
int h = 0;
Iterator<E> i = iterator();
while (i.hasNext()) {
E obj = i.next();
if (obj != null)
h += obj.hashCode();
}
return h;
}

如果两个哈希集是不同的对象,为什么它们共享相同的哈希码?

使用HashSet,使用集合的内容计算hashCode。因为这只是数字加法,加法的顺序无关紧要——把它们加起来就行了。因此,有两个集合是有意义的,每个集合包含等效的对象(因此应该具有匹配的hashCode()值),然后每个集合中的hashCode的总和是相同的。

会像if(set1.hashCode() == set2.hashCode()) doStuff()是有效的代码吗?

确定。

编辑:比较两个集合是否相等的最好方法是使用equals()。在AbstractSet的情况下,调用set1.equals(set2)将导致在集合内的对象级别上单独调用equals()(以及一些其他检查)。

为什么具有相同数据的两个不同的hashset具有相同的HashCode吗?

实际上,这是为了满足Java中指定的另一个需求。

覆盖Setequals方法,考虑到equals返回true(例如a.equals(b)),如果:

  • aSet类型,bSet类型。
  • ab的大小完全相同。
  • a包含b的所有元素。
  • b包含a的所有元素。

因为默认的equals(只比较相同的内存引用)被Set覆盖,所以根据java指南,hashCode方法也必须被覆盖。因此,提供hashCode的自定义实现是为了与equals的自定义实现相匹配。

为了了解为什么在覆盖equals方法时有必要覆盖hashCode方法,您可以看看我之前的回答。

如果两个哈希集不同,为什么它们共享相同的哈希码对象

因为正如上面解释的那样,这是必要的,这样Set就可以拥有equals目前拥有的自定义功能。

如果你只想检查ab是否是不同的set实例,你仍然可以用==!=运算符来检查。

a == b->true表示ab指向内存中Set的同一个实例

a != b->true表示ab指向内存中Set的不同实例

相关内容

  • 没有找到相关文章

最新更新