avatar

为什么重写equals方法后一定要重写hashCode方法?

equals方法

在java的Object类中,equals()比较的是两个对象的引用地址,如果是基本数据类型比较的就是值。

为什么说重写equals方法后一定要重写hashcode方法?

我的理解就是 ,当在使用HashSet(这里只拿HashSet展开)的去重机制时,他会将存入HashSet的元素进行去重处理,那么是如何进行去重的呢?HashSet底层用的是Hash表的一种数据结构(一个元素为链表的数组)
他会首先判断要添加的元素的hash值,同过hash值的计算算出该元素在其底层数组中的索引,查看索引处是否存在元素,如果存在则使用equals方法,如果为true则不添加,如果为false则添加在次索引处。

1
2
3
4
5
6
7
整理一下差不多如下
执行顺序:
首先比较哈希值是否相同
相同:继续执行equals()方法
返回true:元素重复了,不添加
返回false:直接把元素添加到集合
不同:就直接把元素添加到集合

此时如果我定义一个Student类,只重写equals方法如下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Student{
private int age;
private String name;

public Student(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Student student = (Student) o;
if (age != student.age) {
return false;
}
return name != null ? name.equals(student.name) : student.name == null;
}
}
1
2
3
4
5
Student student1 = new Student(1,"张三");
Student student2 = new Student(1,"张三");
System.out.println(student1.equals(student2));//true
System.out.println(student1.hashCode());//1163157884
System.out.println(student2.hashCode());//1956725890

发现其equals相同,而hashcode是不相同的,因为他调用的是父类Object的hashCode方法,而equals相同而hashcode值不同,这样在HashSet集合中是不允许的,因为他先判断其hashCode值,发现不相同就直接插入在集合中了,达不到去重的效果,所以重写了equals方法一定要重写hashCode方法

1
2
//它是一个本地方法,它的实现与本地机器有关,这里我们暂且认为他返回的是对象存储的物理位置(实际上不是,这里写是便于理解)。
public native int hashCode();

有关hashCode的规定:

  • 两个对象相等,其hashcode值一定相同;
  • 两个对象不相等,其hashcode值有可能相同;
  • hashcode相同的两个对象,不一定相等;
  • hashcode不相同的两个对象,一定不相等;
文章作者: Hobo
文章链接: https://hobo-clh.github.io/2020/06/05/%E9%87%8D%E5%86%99equals%E6%96%B9%E6%B3%95%E4%B8%80%E5%AE%9A%E8%A6%81%E9%87%8D%E5%86%99hashCode%E6%96%B9%E6%B3%95/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Hobo's blog
打赏
  • 微信
    微信
  • 支付宝
    支付宝

评论