【问题标题】:Why is the implementation of Object.equals() not using hashCode()?为什么 Object.equals() 的实现不使用 hashCode()?
【发布时间】:2013-08-26 14:04:42
【问题描述】:

“为什么 Sun/Oracle 的家伙每次都强迫我们同时覆盖 equals() 和 hashCode()?”

Everyone knows 说,如果你覆盖一个对象的 equals() 或 hashCode(),你也必须覆盖另一个,因为这两者之间有一个契约:

请注意,只要此方法 [即equals()] 被重写,以维护 hashCode 方法的一般合同,该合同规定相等的对象必须具有相等的哈希码。 -- API doc of Object.equals()

为什么在 Object 类中没有这样实现:

public boolean equals(Object obj) {
    return this.hashCode() == obj.hashCode()
}

如果他们这样做了,世界其他地方就不必同时实施这两种方法了。只覆盖 hashCode() 就足够了。

我想这些家伙有充分的理由不这样做。我只是看不到它 - 请帮我解决这个问题。

【问题讨论】:

  • 可能是因为:如果两个对象相等,它们的hashcode将相等,但是如果两个对象的hashcode相等,则没有足够的信息来保证对象本身是相等的,因为这个事实:哈希可能会发生冲突。
  • 不同的对象仍然可以有相同的hashcode()。只有2^32ints。
  • 常见逻辑错误:x -> y不代表y -> x
  • 顺便提一下,你的代码的一个更短的版本是this.hashCode() == obj.hashCode()。它还可以避免自动装箱(它仍然是不正确的;-))
  • @Joachim thx - 我改变了它

标签: java equals


【解决方案1】:

如果 a.equals(b) 返回 true,则 a.hashCode() == b.hashCode() 必须评估为 true

相反的是不正确!拥有两个a.hashCode() == b.hashCode() 为真但a.equals(b) 为假的对象是完全有效的。

事实上,这是必要的hashCode() 有 232 个可能的返回值。在任何给定时刻,JVM 都可以容纳 超过 232 个对象(假设有足够的内存,这在当今是很有可能的)。假设没有一个对象彼此相等(很容易做到,只要让它们成为"s1""s2",...),那么你必然会发生碰撞校验和(见Pidgeonhole principle)。

事实上,这是最简单的hashCode 实现,对于每个类正确(否则非常糟糕) *:

public int hashCode() {
  return 0;
}

它神奇地满足了the general hashCode() contract的所有要求。

* 除了那些必须实现已定义和记录的hashCode 算法的类,主要示例是String.hashCode()

【讨论】:

  • 好点,但是 hashCode() 的文档也告诉我们:“但是,程序员应该意识到,为不相等的对象生成不同的整数结果可能会提高哈希表的性能。”但该建议与标准实施不一致。如果你的类可以有超过 2^32 个不同的实例,你仍然可以覆盖 equals()。
  • 带有字符串的示例是"FB""Ea"
  • @FrancoisBourgeois:是的,这就是为什么我上面展示的实现是一个坏主意。生成perfect hash 并不总是那么容易,即使在可能的情况下也是如此。所以假设它总是被实施,是一个相当冒险的举动。
【解决方案2】:

Joachim 是正确的,但还有另一个原因:效率。

计算哈希码的成本可能很高,如果调用了equals(),但从来没有调用过hashCode(),那么这项工作将是不必要的。

有很多情况是这样的;只有像Hashtable(或使用它的类)这样的类调用hashCode()

【讨论】:

  • 是的! equals() 通常比对应的 hashCode() 调用更快(尤其是在对象不相等的情况下)。
【解决方案3】:

有无限数量的对象具有相同的 hashcOde。这意味着您不能单独比较 hashCde。

一个简单的例子是Long.hashCode():每个Long 值是1L << 32 + 1 的倍数,其hashCode 为0

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-03
    • 1970-01-01
    • 2015-11-12
    • 1970-01-01
    • 2020-08-02
    • 2012-11-16
    • 2019-06-25
    相关资源
    最近更新 更多