为什么重写 equals 时必须重写 hashCode 方法?
相信这个问题大部分小伙伴即使面试中没有被问到过,但肯定也听说过
那么这个问题到底是为什么?该怎么回答?今天我皮皮虾就来告诉各位小伙伴们
当然,如果对各位有那么亿点点小作用的话,那么期待大家的一键三连哦!
使用hashcode方法提前校验,可以避免每一次比对都调用equals方法,提高效率
例如 HashSet是具有不可重复性的,每次往里面添加数据时,都会先计算该数据的 哈希值(即在哈希表中的存放位置),然后与set中已经存在的数据的 哈希值进行比较,如果都不同则添加在计算出的位置进行添加,如果相同则调用 equals方法进行判断,相同则不添加,不相同则散列到其他位置添加。
因为不同对象出现 哈希值相同的概率是比较低的,所以重写了 hashcode方法可以减少 equals方法的调用,提高效率。
保证同一个对象,保证在equals相同的情况下hashcode值必定相同,如果重写了equals而未重写hashcode方法,可能就会出现两个没有关系的对象equals相同的(因为equal都是根据对象的特征进行重写的),但hashcode不相同,这样就不符合期望。
public class test {
public static void main(String[] args) {
HashSet<User> users = new HashSet<>();
users.add(new User(10,"111"));
users.add(new User(10,"111"));
for (User i : users) {
System.out.println(i);
}
}
}
class User {
int age;
String name;
public User(int age, String name) {
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "User{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return age == user.age &&
Objects.equals(name, user.name);
}
// @Override
// public int hashCode() {
// return Objects.hash(age, name);
// }
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
为什么会这样?
前文已经提过:保证同一个对象,保证在equals相同的情况下hashcode值必定相同,因为自定义对象都是new出来的,所以地址不同,那么hashCode很大概率不同,所以不会出现哈希冲突,就不会调用equals去进行判断,那么这两个特征相同的对象(也就是我们觉得应该是一样的对象) 就成功加入到HashSet中去了。
public class test {
public static void main(String[] args) {
HashSet<User> users = new HashSet<>();
users.add(new User(10,"111"));
users.add(new User(10,"111"));
for (User i : users) {
System.out.println(i);
}
}
}
class User {
int age;
String name;
public User(int age, String name) {
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "User{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return age == user.age &&
Objects.equals(name, user.name);
}
@Override
public int hashCode() {
return Objects.hash(age, name);
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
可见对象被判定为重复,所以只有一份。
原理解析:因为重写了hashCode方法,那么对于特征相同的对象,那么他们的hash值是一样的,所以会出现hash冲突,出现了hash冲突就会去调用equals方法进行判断是否为同一个对象,因为重写了equals方法,那么这两个对象被判定为重复,所以HashSet里面只有一份。
我是 Code皮皮虾,未来的日子里会不断更新出对大家有益的博文,期待大家的关注!!!
创作不易,如果这篇博文对各位有帮助,希望各位小伙伴可以点赞和关注我哦,感谢支持,我们下次再见~~~
分享大纲
大厂面试题专栏
Java从入门到入坟学习路线目录索引
开源爬虫实例教程目录索引
更多精彩内容分享,请点击 Hello World (●’◡’●)