文章目录
HashCode简介
equals简介
1、类中重写HashCode和equals方法比较两个对象是否相等
2、HashSet保证元素的唯一性
HashCode简介
hashCode()方法的作用是获取哈希码,返回的是一个int整数
Object类中的equals()方法定义如下
public native int hashCode();
1
哈希码的作用是确定对象在哈希表的索引下标。比如HashSet和HashMap就是使用了hashCode方法确定索引下标。如果两个对象返回的hashCode相同,就被称为“哈希冲突”。
equals简介
equals()方法的作用很简单,就是判断两个对象是否相等,equals()方法是定义在Object类中,而所有的类的父类都是Object,所以如果不重写equals方法则会调用Object类的equals方法。
Object类中的equals()方法定义如下
public boolean equals(Object obj) {
return (this == obj);
}
1
2
3
在equals()方法中的==,那么在Java中有什么含义呢,
我们都知道在Java中分为基本数据类型和引用数据类型。那么==在这两个类型中作用是不一样的。
基本数据类型:比较的是两边值是否相等
引用数据类型:比较的是两边内存地址是否相等
基本数据类型包括:byte,short,char,int,long,float,double,boolean
而通过Java文档中的equals()方法描述,所有要实现自己的equals()方法都要遵守下面几个规则
自反性:对于任何对象x,x.equals(x)应该返回true。
对称性:对于任何两个对象x和y,如果x.equals(y)返回true,那么y.equals(x)也应该返回true。
传递性:对于多个对象x,y,z,如果x.equals(y)返回true,y.equals(z)返回true,那么y.equals(z)也应该返回true。
一致性:对于两个非空对象x,y,在没有修改此对象的前提下,多次调用返回的结果应该相同。
对于任何非空的对象x,x.equals(null)都应该返回false。
1、类中重写HashCode和equals方法比较两个对象是否相等
两个对象通过equals比较是相等的,那么HashCode肯定相等。
两个对象通过HashCode比较是相等的,那么equals不一定相等。
因此,equals 方法被覆盖过,则 hashCode 方法也必须被覆盖
面试题:
重写equals()方法就可以比较两个对象是否相等,为什么还要重写hashcode()方法呢?
因为HashSet、HashMap底层在添加元素时,会先判断对象的hashCode是否相等,如果hashCode相等才会用equals()方法比较是否相等。换句话说,HashSet和HashMap在判断两个元素是否相等时,会先判断hashCode,如果两个对象的hashCode不同则必定不相等。
以下是源码展示:
2、HashSet保证元素的唯一性
代码演示:
有一个User类,只重写equals()方法,然后放到HashSet集合中去重
public class User {
private String id; private String name; private Integer age; public User(String id, String name, Integer age) { this.id = id; 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; User user = (User) o; return Objects.equals(id, user.id) && Objects.equals(name, user.name) && Objects.equals(age, user.age); } //此处省略getter、setter、toString方法
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
然后我们循环创建3个成员变量的值都是一样的User对象,最后放到Set集合中去重
public static void main(String[] args) {
List list = new ArrayList<>();
for (int i = 0; i < 3; i++) {
User user = new User(“1”, “张三”, 18);
list.add(user);
}
Set set = new HashSet<>(list);
for (User user : set) {
System.out.println(user);
}
}
1
2
3
4
5
6
7
8
9
10
11
按道理我们预期会去重,只剩下一个“张三”的user,但实际上因为没有重写hashCode方法,所以没有去重。
运行结果
接着我们在User类里面重写一些hashCode方法再试试,其他不变
public class User {
//其他不变
//重写hashCode方法 @Override public int hashCode() { return Objects.hash(id, name, age); }
}
1
2
3
4
5
6
7
8
9
运行结果
究其原因在于HashSet会先判断hashCode是否相等,如果hashCode不相等就直接认为两个对象不相等,不会再用equals()比较了。我们不妨看看重写hashCode方法和不重写hashCode方法的哈希码。
这是不重写hashCode方法的情况,每个user对象的哈希码都不一样,所以HashSet会认为都不相等。
那么有些人看到这里,就会问,如果两个对象返回的哈希码都是一样的话,是不是就一定相等?
答案是不一定的,因为HashSet、HashMap判断哈希码相等后还会再用equals()方法判断。
总结:
1.HashCode方法和equals方法都是Object类中的方法,即所有对象都有equals方法和HashCode方法;
2.两个对象通过equals比较是相等的,那么HashCode肯定相等;相反的,两个对象通过HashCode比较是相等的,那么equals不一定相等;
3.只要重写equals方法,就必须重写HashCode方法;
完!
————————————————
版权声明:本文为CSDN博主「华山之仔」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/huashanzhizai/article/details/118882005