或“为什么Sun / Oracle人员每次都强迫我们覆盖equals()和hashCode()?”
Everyone knows,如果你覆盖一个对象的equals()或hashCode(),你也必须覆盖另一个,因为这两者之间有契约:
请注意,通常需要在此方法时覆盖hashCode方法[即重写equals()],以便维护hashCode方法的一般契约,该方法声明相等的对象必须具有相等的哈希码。 - API doc of Object.equals()
为什么不在Object类中实现这种方式:
public boolean equals(Object obj) {
return this.hashCode() == obj.hashCode()
}
如果他们这样做了,它将使世界其他地方免于必须实施这两种方法。只覆盖hashCode()。
就足够了我猜这些家伙有充分的理由不这样做。我只是看不到它 - 请为我清楚。
答案 0 :(得分:12)
如果a.equals(b)
返回true,则a.hashCode() == b.hashCode()
必须评估为true
。
相反的是不正确!有两个a.hashCode() == b.hashCode()
为真的对象是完全有效的,但a.equals(b)
为假。
事实上,那是必要的。 hashCode()
有2个 32 可能的返回值。在任何给定时刻,JVM可以容纳多于 2 32 对象(假设有足够的内存,这些天很可能)。假设没有任何对象彼此相等(容易做到,只需让它们为"s1"
,"s2"
,...),那么你绑定到发生校验和冲突(见Pidgeonhole principle)。
事实上,对于每个类 <,这是更正(但在非常糟糕)的最简单的hashCode
实现< SUP> * :
public int hashCode() {
return 0;
}
它神奇地满足the general hashCode()
contract的所有要求。
*除了那些具有必须实现的已定义和记录的hashCode
算法的类,主要的例子是String.hashCode()
。
答案 1 :(得分:3)
约阿希姆是正确的,但还有另一个原因:效率。
计算哈希代码可能会很昂贵,如果调用equals()
,则会不必要地付出这种努力,但hashCode()
永远不会。
在很多情况下会出现这种情况;只有Hashtable
(或使用它)的类才会调用hashCode()
。
答案 2 :(得分:1)
有无数个对象具有相同的hashcOde。这意味着您无法单独比较hashCde。
一个简单的示例是Long.hashCode()
:Long
的倍数的每个1L << 32 + 1
值都具有0
的hashCode。