为什么重写 equals 时必须重写 hashCode 方法?

因为不重写的话,set等不允许元素重复的散列表里会出现重复的元素。
因为散列表中先判断hashCode,相等后才会比较equals。

验证一下,首先我们先创建一个Person类,并重写equals方法(先不重写hashCode方法)

@AllArgsConstructor
public class Person {
    private String name;    
    private String sex;    
    public String getName() {        
        return name;    
    }    
    
    public void setName(String name) {
        this.name = name;    
    }    
    
    public String getSex() {
        return sex;    
    }    
    
    public void setSex(String sex) {
        this.sex = sex;    
    }    
    
    @Override
    public String toString() {
        return "Person{" +
            "name='" + name + '\'' +
            ", sex=" + sex +
            '}';    
    }    
    
    @Override    
    public boolean equals(Object o) {
        if (this == o) return true;        
        if (o == null || getClass() != o.getClass()) 
            return false;        
        Person person = (Person) o;       
        return Objects.equals(name, person.name) &&                
            Objects.equals(sex, person.sex);    
    }
}

然后new两个内容一样的Person实例,比较一下equals是否相等,再将其分别放入HashSet中,打印一下set中的内容。

    public static void main(String[] args) {
     
        Person person1 = new Person("Van Darkholme","♂");
        Person person2 = new Person("Van Darkholme","♂");

        System.out.println(person1.equals(person2));

        Set<Person> set = new HashSet<>();

        set.add(person1);
        set.add(person2);

        System.out.println(set.toString());
    }

我们知道HashSet中是不会拥有重复元素的。所以上面程序我们期望set中只有一个元素。

运行一下:

true
[Person{name='Van Darkholme', sex=♂}, Person{name='Van Darkholme', sex=♂}]

发现两个元素equals为true,说明两个元素相等,但是set中却出现了两个相同的元素。

看一下HashSet中add的源码,跟踪到HashMap的putVal方法。

为什么重写 equals 时必须重写 hashCode 方法?_第1张图片

我们可以看到方法中先比较元素的HashCode,如果相等再比较是否==或者equals是否为true,条件都成立才会元素替换。

我们通过打印的HashCode发现,两个实例的hashCode不同,当然也就不会进行equals的判断了。直接判断两个元素不同。

person1:966808741
person2:1908153060

相同的原理,如果重写equals不重写hashCode,HashMap中的key也会出现一样的问题。

你可能感兴趣的:(Java,java,hashcode)