hashCode()和equals()

1.hashCode()和equals()方法概述

hashCode()equals() 是 Java 中两个重要的方法,通常一起被使用以实现对象的相等比较。

hashCode() 方法返回对象的哈希码值,用于支持基于哈希表的数据结构,如哈希表、哈希集合和哈希映射。哈希码是一个整数值,可以理解为将对象映射到一个桶中的索引,这样可以更快速地查找和存储对象。如果两个对象根据 equals() 方法相等,那么它们的哈希码必须相等。反之,如果两个对象的哈希码相等,它们并不一定相等。

equals() 方法用于比较对象是否相等。在 Java 中,对象之间有两种相等的概念:引用相等和值相等。引用相等指的是两个对象引用的是同一个对象,即它们在内存中的地址相同。值相等指的是两个对象在逻辑上相等,即它们的属性值相等。默认情况下,equals() 方法比较的是两个对象的引用地址,因此需要重写该方法以实现值相等的比较。在实现 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 (o == this) return true;
        if (!(o instanceof Person)) return false;
        Person p = (Person) o;
        //这个equals是String类的equals方法,String类重写了该方法,改成了值比较
        return p.name.equals(name) && p.age == age; 
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

以上代码中,equals()方法就是比较两个Person对象name和age是否相等(也可以只比较name),默认是比较两个对象的内存地址是否相等,hashCode()方法返回name和age一起hash后的哈希值,而不是返回这个Person对象的哈希值。

2.为什么重写equals()方法必须重写hashCode()方法

在Java中,如果我们重写了一个对象的equals方法,我们通常也应该重写它的hashCode方法。这是因为在使用集合类(如HashMap、HashSet等)时,这些类使用hashCode方法来确定对象在集合中的存储位置。如果我们没有重写hashCode方法,而只重写了equals方法,则可能会导致两个相等的对象被存储在集合中的不同位置,从而导致集合操作出现问题。具体来说,如果我们重写了equals方法但没有重写hashCode方法,则会破坏散列表的契约(equals相等的对象必须具有相同的散列值),从而可能导致集合类中的查找等操作失效或效率降低。因此,我们应该确保重写的equals方法与hashCode方法一致,以确保在使用集合类时能够正常工作。

3.hashCode()方法和equals()方法互相推证

在Java中,如果两个对象的equals()方法返回true,则它们的hashCode()方法必须返回相同的值,这是因为在使用散列表等数据结构时,它们通常使用hashCode()方法来确定对象的存储位置,如果两个对象的hashCode()值不同,则它们会被认为是不同的对象,即使它们的equals()方法返回true,这样会导致散列表无法正常工作。但是反过来不成立,即如果两个对象的hashCode()方法返回相同的值,并不意味着它们一定相等,因为hashCode()方法存在哈希冲突的情况,也就是不同的对象可能会有相同的hashCode()值[1]。因此,在重写equals()方法的同时,也应该重写hashCode()方法以满足这个规定。

一句话概括:equals相等hashCode也一定相等,因为散列表用hashcode方法确定对象,要保证散列表等数据结构正常工作。

hashCode相等equals不一定相等,因为存在哈希冲突,两个不同的对象也可能hashCode相等。