【问题标题】:"Deep equality" test and hashCode()“深度相等”测试和 hashCode()
【发布时间】:2011-09-13 20:35:51
【问题描述】:

假设一个类MyClass 有3 个变量,abc。该类还覆盖了使用 Joshua Bloch 的方法计算返回值的 hashCode()。

假设上述情况,如果 MyClass()new MyClass() 的哈希码匹配,那么假设它们是完全相等的是否正确?

出于示例的目的,假设两个对象都使用相同的参数进行初始化

【问题讨论】:

  • 您可能想澄清一下 Josh Bloch 对于不熟悉的人的方法。
  • 是的,只是出于好奇,那会是什么?我的意思是很明显(鸽子等) hashCode 通常不能是唯一的,所以我认为这是为有限的已知数据集创建完美哈希的某种方法?

标签: java object


【解决方案1】:

当然不会。

hashCode 需要为等价对象产生相同的值,但不同的对象可能产生相同的值。因此,以下是正确的(但效率低下)hashCode 实现:

public int hashCode()
{
    return 42;
}

即使您知道使用了特定的散列方法,假设hashCode 是完美的也是一个坏主意:稍后,一些重构/子类可能会用其他东西替换hashCode 实现。如果你想要这个,创建一个总是返回完美哈希码的perfectHashCode 方法,并使用它来实现hashCode

回答您最初的问题:不,即使 Bloch 的方法 afaics 也不会产生完美的 hashCode,因为(因为包装了 MAXINT)2 条不同的路径最终可能会碰撞到相同的哈希码中。

这很容易想象:假设您的对象包含 2 个整数。哈希码只有 1 个整数。所以它永远不会为 2 个整数的每个组合产生不同的值。

【讨论】:

  • 阅读 OP 的第二句:“这个类还覆盖了 hashCode(),它使用 Joshua Bloch 的方法计算返回值。”
  • 你当然是对的。扩展答案以解释为什么您也不能对他的实施做出这种假设。
【解决方案2】:

如果它们的哈希码匹配,您永远不能假设两个对象相等。哈希码相等仅意味着对象可能相等并且必须调用equals 来确定。哈希码不同意味着对象肯定相等(前提是hashCode() 正确一致equals)。

【讨论】:

    【解决方案3】:

    其他答案是正确的,但这里有另一种查看方式:hashCode 返回int。如果您有一个对象,其唯一成员是 String,并且该字符串包含超过 4 个字节的字符,那么您在该 String 中已经拥有比使用 int 表达的更多信息。一旦意识到这一点,就会清楚hashCode 返回的值不可能是对象的完整表示。

    由于hashCode返回的值不能完全代表对象,显然不能用来判断对象在语义上是否相等。

    如果两个对象的hashCodes 相等,您可以做一件事:您可以假设它们是同一个对象的可能性相当合理。因此,例如HashMap 首先根据哈希码定位一个哈希桶,然后查看它在其中找到的每个对象(使用equals)以找到一个语义上与您实际想要的对象等效的对象。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-23
      • 2012-11-27
      • 1970-01-01
      • 1970-01-01
      • 2012-01-12
      • 2015-10-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多