继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

HashCode()和equals()的区别

幕布斯7119047
关注TA
已关注
手记 432
粉丝 28
获赞 102

文章目录
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

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP