面试题:Java 中的 hashCode 和 equals 方法之间有什么关系?

在 Java 中,hashCode()equals() 方法是 Object 类中的两个重要方法,它们用于定义对象的相等性和哈希值。这两个方法之间有着紧密的关系,尤其是在将对象用作集合(如 HashMap, HashSet 等)中的键时尤为重要。

关系

  1. 一致性要求:如果两个对象通过 equals() 方法比较是相等的,那么这两个对象的 hashCode() 方法返回的哈希码也必须相同。这是为了确保在使用基于哈希的集合类(例如 HashMap, HashSet)时,能够正确地检索对象。违反这一原则可能导致这些集合无法正常工作,比如查找失败或丢失数据。
  2. 非强制性逆向关系:相反的情况并不一定成立。即如果两个对象的 hashCode() 相同,并不意味着这两个对象通过 equals() 比较一定是相等的。这是因为哈希冲突的存在,不同的对象可能会有相同的哈希码。当两个对象的哈希码相同时,需要进一步通过 equals() 方法来确定这两个对象是否真正相等。

为什么这很重要?

  • 性能优化hashCode() 的作用之一是在哈希表中快速定位到桶的位置。如果 hashCode() 方法设计得不好(例如总是返回同一个值),则会导致哈希表退化为链表,大大降低查找效率。
  • 正确性保证:正确实现 equals() 方法对于判断对象是否相等至关重要。而在基于哈希的集合中,正确的 hashCode() 实现同样重要,以保证集合操作(添加、删除、查询)的准确性。

自定义类时的注意事项

当你在一个自定义类中重写 equals() 方法时,通常也需要重写 hashCode() 方法,以保持上述的一致性要求。否则,可能会导致不可预见的行为,特别是在使用该类的对象作为哈希集合的键时。

示例

public class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Person person = (Person) o;

        if (age != person.age) return false;
        return name != null ? name.equals(person.name) : person.name == null;
    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        return result;
    }
}

在这个例子中,我们根据 nameage 字段重写了 equals()hashCode() 方法,确保了当两个 Person 对象的 nameage 都相同时,它们被认为是相等的,且具有相同的哈希码。这样可以确保它们在哈希集合中的行为符合预期。

THE END
喜欢就支持一下吧
点赞5 分享