为什么Object.equals()的实现不使用hashCode()?

时间:2013-08-26 14:04:43

标签: java equals

“为什么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()。

就足够了

我猜这些家伙有充分的理由不这样做。我只是看不到它 - 请为我清楚。

3 个答案:

答案 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。