【问题标题】:Does Hashcode equality imply refer reference based equality?Hashcode 相等是否意味着引用基于引用的相等?
【发布时间】:2011-08-14 22:45:02
【问题描述】:

我读到要在 java 中使用 equals() 方法,我们还必须重写 hashcode() 方法,并且相等(逻辑上)的对象应该具有相同的哈希码,但这并不意味着基于参考的平等!这是我重写的 equals() 方法的代码,我应该如何重写 hashcode 方法:

@Override    
public boolean equals(Object o)
        {
            if (!(o instanceof dummy))
                return false;
            dummy p = (dummy) o;
            return (p.getName() == this.getName() && p.getId() == this.getId() && p.getPassword() == this.getPassword());

        } 

我只是想了解它是如何工作的,所以只有三个字段,即 nameidpassword ,只是尝试比较我在 main() 中定义的两个对象就是这样!我还需要知道是否总是需要重写 hashcode() 方法和 equals() 方法?

【问题讨论】:

  • 记住'return 1;'是 'hashcode();' 的完全合法的实现这通常总结了您可以信任和不信任的内容:)
  • 小心!您的部分 p.getName() == this.getName() 和 p.getPassword() == this.getPassword() 不正确(假设它们是字符串或非原语)。您应该使用 p.getName().equals(this.getName()) 和 p.getPassword().equals(this.getPassword())。您还应该添加空检查以访问这两个字段。

标签: java object methods overriding


【解决方案1】:

哈希码相等并不意味着任何事情。然而,hashcode inequality 应该暗示equals 将产生错误,并且任何两个相等的项目应该总是具有相同的hashcode。

因此,用 equals 覆盖哈希码总是明智的,因为许多数据结构都依赖它。

【讨论】:

    【解决方案2】:

    即使未能覆盖hashCode() 只会破坏您的类在HashSetHashMap 和其他hashCode 相关结构中的使用,您仍应覆盖hashCode() 以维护Object 描述的合同。

    大多数hashCode() 实现的一般策略是组合用于确定相等性的字段的哈希码。在您的情况下,合理的hashCode() 可能看起来像这样:

    public int hashCode(){
        return this.getName().hashCode() ^ this.getId() ^ this.getPassword().hashCode();
    }
    

    【讨论】:

      【解决方案3】:

      当您覆盖 equals() 时,您需要覆盖 hashCode()。仅仅使用equals() 不足以要求您覆盖hashCode()

      【讨论】:

        【解决方案4】:

        在您的代码中,您实际上并没有比较字段的值。使用equals() 而不是== 以使您的实现相等正确。

        return (p.getName().equals(this.getName()) && ...
        

        (请注意,如果getName() 返回null,则上述代码可能会导致空引用异常:您可能希望使用here 所述的实用程序类)

        是的,hashCode() 会在您使用 HashMap、HashSet 等哈希数据结构时被调用

        您必须在每个 覆盖 equals() 的类。失败 这样做将导致违反 总合同 Object.hashCode(),这将防止 你的班级无法正常运作 结合所有基于哈希的 集合,包括 HashMap, HashSet 和 Hashtable。

        来自 Effective Java,作者 Joshua Bloch

        另见

        【讨论】:

        • “在您的代码中,您实际上并没有比较字段的值。使用 equals() 而不是 == 来使您的 equals 实现正确。” - 如果被比较的字段的类型是原始的或不可变的(例如字符串),那么== 将工作得非常好,如果 getter 为空,它也不会失败。
        【解决方案5】:

        hashCode() 的想法是,它是您的对象在给定空间中的唯一表示。保存对象的数据结构使用哈希码来确定放置对象的位置。在Java中,例如HashSet使用对象的哈希码来确定对象位于哪个bucket,然后对于该bucket中的所有对象,它使用equals()来确定是否是匹配的。

        如果您不覆盖 hashCode(),但确实覆盖 equals(),那么您将达到一个点,即您认为 2 个对象相等,但 Java 集合看不到以同样的方式。这会导致很多奇怪的行为。

        【讨论】:

        • -1 HashSet 不使用哈希码来确定对象是否已经是集合的一部分。它仅使用它来确定查看位置。
        • 从技术上讲,你是对的,哈希来确定存储桶,然后检查等于以确定它是否在那里......我会澄清
        • '它是您对象的唯一表示'。不,没有唯一性要求。
        • 不仅没有唯一性要求,而且不可能为每个(128 位)GUID 提供唯一的 32 位哈希码。除此之外,还有一个预期是 ifa.equals(b),然后 a.hashCode() == b.hashCode()`,这意味着有时两个对象预期具有相等的哈希码.
        猜你喜欢
        • 1970-01-01
        • 2018-11-16
        • 1970-01-01
        • 2018-02-12
        • 2014-08-15
        • 1970-01-01
        • 2019-08-25
        • 2017-11-17
        • 1970-01-01
        相关资源
        最近更新 更多