我最近在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中指定的另一个需求。
覆盖Set
的equals
方法,考虑到equals
返回true(例如a.equals(b)
),如果:
a
为Set
类型,b
为Set
类型。a
和b
的大小完全相同。a
包含b
的所有元素。b
包含a
的所有元素。
因为默认的equals
(只比较相同的内存引用)被Set
覆盖,所以根据java指南,hashCode
方法也必须被覆盖。因此,提供hashCode
的自定义实现是为了与equals
的自定义实现相匹配。
为了了解为什么在覆盖equals
方法时有必要覆盖hashCode
方法,您可以看看我之前的回答。
如果两个哈希集不同,为什么它们共享相同的哈希码对象
因为正如上面解释的那样,这是必要的,这样Set
就可以拥有equals
目前拥有的自定义功能。
如果你只想检查a
和b
是否是不同的set实例,你仍然可以用==
和!=
运算符来检查。
a == b
->true表示a
和b
指向内存中Set的同一个实例
a != b
->true表示a
和b
指向内存中Set的不同实例