为什么我需要重写 Java 中的 equals 和 hashCode 方法?

2023-12-09

最近我读到了这篇文章开发者作品文档.

该文档主要是关于定义hashCode() and equals()有效且正确,但是我无法弄清楚为什么我们需要重写这两种方法。

我如何决定有效地实施这些方法?


Joshua Bloch 在《Effective Java》中说道

您必须在每个重写 equals() 的类中重写 hashCode()。如果不这样做,将导致违反 Object.hashCode() 的一般契约,这将阻止您的类与所有基于哈希的集合(包括 HashMap、HashSet 和 Hashtable)一起正常运行。

让我们尝试通过一个例子来理解它,如果我们重写会发生什么equals()不覆盖hashCode()并尝试使用Map.

假设我们有一个这样的类和两个对象MyClass相等,如果他们的importantField是相等的(与hashCode() and equals()由 eclipse 生成)

public class MyClass {
    private final String importantField;
    private final String anotherField;

    public MyClass(final String equalField, final String anotherField) {
        this.importantField = equalField;
        this.anotherField = anotherField;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result
                + ((importantField == null) ? 0 : importantField.hashCode());
        return result;
    }

    @Override
    public boolean equals(final Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        final MyClass other = (MyClass) obj;
        if (importantField == null) {
            if (other.importantField != null)
                return false;
        } else if (!importantField.equals(other.importantField))
            return false;
        return true;
    }
}

想象一下你有这个

MyClass first = new MyClass("a","first");
MyClass second = new MyClass("a","second");

仅覆盖equals

If only equals被覆盖,那么当你打电话时myMap.put(first,someValue)首先将散列到某个存储桶,当您调用时myMap.put(second,someOtherValue)它将散列到其他一些存储桶(因为它们有不同的hashCode)。因此,尽管它们相等,但由于它们不散列到同一个存储桶,因此映射无法实现这一点,并且它们都保留在映射中。


虽然没有必要重写equals()如果我们重写hashCode(),让我们看看在这种特殊情况下会发生什么,我们知道两个对象MyClass相等,如果他们的importantField是相等的,但我们不覆盖equals().

仅覆盖hashCode

如果你只覆盖hashCode然后当你打电话时myMap.put(first,someValue)它首先需要计算它的hashCode并将其存储在给定的桶中。然后当你打电话时myMap.put(second,someOtherValue)它应该根据以下内容将第一个替换为第二个地图文档因为它们是平等的(根据业务要求)。

但问题是equals没有被重新定义,所以当map散列时second并遍历桶查找是否有对象k这样second.equals(k)是真的,它不会找到任何作为second.equals(first)false.

希望已经清楚了

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么我需要重写 Java 中的 equals 和 hashCode 方法? 的相关文章

随机推荐