为什么重写 equals 时必须重写 hashCode 方法?
程序员文章站
2024-03-25 22:50:52
...
因为不重写的话,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方法。
我们可以看到方法中先比较元素的HashCode,如果相等再比较是否==或者equals是否为true,条件都成立才会元素替换。
我们通过打印的HashCode发现,两个实例的hashCode不同,当然也就不会进行equals的判断了。直接判断两个元素不同。
person1:966808741
person2:1908153060
相同的原理,如果重写equals不重写hashCode,HashMap中的key也会出现一样的问题。
推荐阅读
-
重写hashcode和equals方法
-
为什么重写equals时还必须重写hashcode方法
-
为什么重写 equals 时必须重写 hashCode 方法?
-
为什么重写equals就必须重写hashCode
-
修改equals方法时为什么还要重写hashcode方法?
-
如果使用Object作为HashMap的Key,为什么要重写hashcode和equals
-
JAVA - 【为什么要重写hashCode和equals?】HashSet
-
HashMap中的key为什么不能为可变对象(除非重写它的hashcode方法和equals方法)
-
HashMap中对象作Key为什么要重写equals和hashcode
-
当集合中的对象要去重时,为什么要重写hashCode和equals方法