首页 > 其他分享 >为什么重写equals一定要重写hashCode方法?

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

时间:2022-11-01 12:35:22浏览次数:43  
标签:name 重写 equals hashCode User 方法


分享知识 传递快乐

 

 

equals方法和hashCode方法都是Object类中的方法。

equals方法在其内部是调用了"==",所以说在不重写equals方法的情况下,equals方法是比较两个对象是否具有相同的引用,即是否指向了同一个内存地址。而hashCode是一个本地方法,他返回的是这个对象的内存地址。

hashCode通用规定

  • 在应用程序的执行期间,只要对象的equals方法的比较操作所用到的信息没有被修改,那么对同一个对象的多次调用,hashCode方法都必须始终返回同一个值。在一个应用程序与另一个应用程序的执行过程中,执行hashCode方法所返回的值可以不一致。
  • 如果两个对象根据equals(Object)方法比较是相等的,那么调用这两个对象中的hashCode方法都必须产生同样的整数结果
  • 如果两个对象根据equals(Object)方法比较是不相等的,那么调用这两个对象中的hashCode方法,则不一定要求hashCode方法必须产生不用的结果。但是程序员应该知道,给不相等的对象产生截然不同的整数结果,有可能提高散列表的性能。

由此可知,如果重写了equals方法而没有重写hashCode方法的话,就违反了第二条规则。相等的对象必须拥有相等的hashcode。

 

不重写hashCode方法所带来的严重后果

public class User {

private Long id;
private String name;

public User(Long id, String name) {
super();
this.id = id;
this.name = name;
}

@Override
public boolean equals(final Object o) {
if (this == o)
return true;
if (!(o instanceof User))
return false;
if (super.equals(o))
return true;

final User user = (User) o;

if (id != null ? !id.equals(user.id) : user.id != null)
return false;
return name != null ? name.equals(user.name) : user.name == null;
}


public static void main(String[] args) {
User u1 = new User(1L, "root");
User u2 = new User(1L, "root");

Map<User, Integer> hashMap = new HashMap<>();
hashMap.put(u1, 1);

System.out.println(u1.equals(u2));
System.out.println(hashMap.containsKey(u2));

}
}

输出结果

true
false

对于第一个输出true我们很容易知道,因为我们重写了equals方法,只要两个对象的name属性相同就会返回ture。但是为什么第二个为什么输出的是false呢?就是因为我们没有重写hashCode方法。所以我们得到一个结论:如果一个类重写了equals方法但是没有重写hashCode方法,那么该类无法结合所有基于散列的集合(HashMap,HashSet)一起正常运作。

 

重写hashCode方法

@Override
public int hashCode() {
int result = 1;
result = 31 * result + (id != null ? id.hashCode() : 0);
result = 31 * result + (name != null ? name.hashCode() : 0);
return result;
}

输出结果

true
true

 

然而重写了equals,且u1.equals(u2)返回true,根据hashcode的规则,两个对象相等其哈希值一定相等,所以矛盾就产生了,因此重写equals一定要重写hashcode,而且从类重写后的hashcode方法中可以看出,重写后返回的新的哈希值与User的两个属性有关。

总结:

  • 两个对象相等,hashcode一定相等
  • 两个对象不等,hashcode不一定不等
  • hashcode相等,两个对象不一定相等
  • hashcode不等,两个对象一定不等

 

 

 

 

 

 

 

 

————————————

如有不妥之处请留言指正。
相互学习,共同进步。

标签:name,重写,equals,hashCode,User,方法
From: https://blog.51cto.com/u_15856116/5813279

相关文章

  • Java-equals和“==”的区别
    “==”是比较运算符,可以用于判断基本数据类型是否相等,当用于判断引用类型的时候,比较的对象的内存地址是否相同equals是Object类当中的方法,不可以用于判断基本数据是否相......
  • c#中,类的重写中,new和override的区别
    在c#中有两种方法可以重写类的成员函数,分别是**new**和**override**,看书时书上并没有说明两者的区别,经过网上查资料后,总结如下:如果使用的是override,则调用的是它实际类的函......
  • equals和hashCode详解
    equals和hashCode详解http://www.cnblogs.com/Qian123/p/5703507.html阅读目录equals()方法详解hashcode()方法详解Hashset、Hashmap、Hashtable与hashcode()和equa......
  • python 封装 多态 继承 重写
    面向对象的三大特征封装:提高程序的安全性继承:提高代码的复用性(继承包括重写)多态:提高程序的可扩展性和可维护性 三大特征的实现:封装:将数据(属性)和......
  • 利用Kong 的 request-transformer 插件重写 URL
    1.背景介绍需求是将URL:www.abc.com/api/item/111 重写成 www.xyz.com/open/item/itemdetail?id=111。且域名不变,不能发生302跳转。2.request-transformerrequest-transf......
  • javaSE13-- API_常用类--默认继承Object--toString()--==与equals()[详解]
    API_常用类API应用程序编程接口API文档是对Java预定定义的类或接口功能和方法功能的说明文档,目的是提供给开发人员进行使用帮助说明默认继承Object,Java中所有类没有显示的......
  • Java - 重载 与 重写 的区别
    静态分派与动态分派1.静态类型[外观类型]=>方法执行版本=>编译期确定2.实际类型=>方法执行版本=>运行期确定静态解析与动态连接1.静态解析:符号引用(c......
  • 11.CF522D Closest Equals 线段树+离线询问
    11.CF522DClosestEquals线段树+离线询问给定序列,查询区间内距离最近的两个相等元素。离线查询,按右端点加入贡献计算答案即可洛谷传送门:​​CF522DClosestEquals-洛谷......
  • Java当中的重载和重写的区别【多测师】
    java中重写与重载的区别1.重写(Override)从字面上看,重写就是重新写一遍的意思。其实就是在子类中把父类本身有的方法重新写一遍。子类继承了父类原有的方法,但有时子类并不......
  • ==和equals()的区别
    ==是运算符,若是基本数据类型,则比较存储的值;若是引用数据类型,则比较引用类型变量所指向对象的地址值。equals()是Object的方法,不能比较基本数据类型,若没有对equals()方法......