在每个类中,在重写equals方法的时侯,一定要重写hashcode方法。

根据Object规范,规范约定:

  1. 如果两个对象通过equals方法比较是相等的,那么它们的hashCode方法结果值也是相等的。
  2. 如果两个对象通过equals方法比较是不相等的,那么不要求它们的hashCode方法结果值是相等的。
  3. 当在一个应用程序执行过程中, 如果equals方法比较中没有修改任何信息,那么在同一个对象上重复调用hashCode方法时,它必须始终返回相同的值。但如果从一个应用程序到了另一个应用程序,两个应用程序汇中调用hashCode方法的返回值可以是不一致的。

Object类中的默认的equals和hashCode方法:

  • equals:比较的是对象的内存地址是否相同(相当于==操作符);
  • hashCode:hashCode方法的返回值符合上述规范。

因此,当只重写equals方法,不重写hashCode时,违反规定:equals相等的对象必须具有相等的哈希码(因为hashCode的返回值还是按照Object类的规范:同一对象的hashCode值相同)。

如果不这样做,你的类违反了hashCode的通用约定,对于HashSet, HashMap, HashTable等基于hash值的类就会出现问题。

以HashMap为例,当集合要添加新的对象时,先调用这个对象的hashCode方法,得到对应的hashcode值,实际上在HashMap的具体实现中会用一个table保存已经存进去的对象的hashcode值,如果table中没有该hashcode值,它就可以直接存进去,不用再进行任何比较了;如果存在该hashcode值,就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址。
这样解决了向含有大量数据的集合中添加元素时,大量频繁的操作equals方法的问题。

下面举个例子说明:
创建一个Point类,有两个成员变量x和y,并重写了equals方法。

public class Point {private final int x, y;public Point(int x, int y) {this.x = x;this.y = y;}@Overridepublic boolean equals(Object obj) {if (this == obj) return true;if (!(obj instanceof Point)) return false;Point point = (Point) obj;return x == point.x && y == point.y;}public static void main(String[] args) {Point p1 = new Point(1, 2);Point p2 = new Point(1, 2);System.out.println(p1.equals(p2));// trueMap<Point, String> map = new HashMap<>();map.put(p1, "p1");System.out.println(map.get(p2)); // null}
}

你可能觉得 map.get(p2) 应该返回字符串 p1, 但是却返回null, 这是因为Point类并没有重写hashCode方法,导致两个相等的实例p1和p2返回了不同的哈希码,违反了hashCode的约定,put方法把实例p1放到了一个哈希桶(hash bucket)中,但因为p2的哈希码不等于p1的哈希码,所以get方法会从其它哈希桶中去查找。

解决这个方法很简单,只需要重写Point类的hashCode方法。

 @Overridepublic int hashCode() {int result = Integer.hashCode(x);result = 31 * result + Integer.hashCode(y);return result;}public static void main(String[] args) {Point p1 = new Point(1, 2);Point p2 = new Point(1, 2);System.out.println(p1.equals(p2));// trueMap<Point, String> map = new HashMap<>();map.put(p1, "p1");System.out.println(map.get(p2)); // p1}

这次你会发现map.get(p2) 返回的就是字符串p1了, 因为hashCode这个方法会返回一个简单的确定性计算的结果,它的唯一的输入是 Point实例中的两个重要的属性x和y,所以显然相等的 Point实例具有相同的哈希码。

此外Objects 类有一个静态方法,它接受任意数量的对象并为它们返回一个哈希码。这个名为 hash 的方法可以 让你编写一行 hashCode 方法,其质量与根据这个项目中的上面编写的方法相当。

 @Overridepublic int hashCode() {return Objects.hash(x, y);}

注意事项

  1. 当你写完 hashCode 方法后,请一定问一下自己是否满足相等的实例有相同的哈希码这一条件。
  2. hashCode中涉及到的属性应与equals中保持一致,不要试图从哈希码计算中排除重要的属性来提高性能。

总之,每次重写 equals 方法时都必须重写 hashCode 方法,否则程序将无法正常运行。你的 hashCode 方 法必须遵从 Object 类指定的常规约定,并且必须执行合理的工作,将不相等的哈希码分配给不相等的实例

原文链接:https://juejin.im/post/5e0226bb6fb9a0165936f44b

为什么重写equals方法时一定要重写hashCode方法相关推荐

  1. hashcode相等的两个对象一定相等吗_为什么重写 equals方法时一定要重写hashCode方法?...

    推荐阅读: 一线架构师总结SpringBoot,Cloud,Nginx与Docker,不信你搞不懂 47天洒热血复习,我终于"挤进"了字节跳动(附面经+学习笔记) 五年时间,从蘑菇 ...

  2. Java重写equals方法时为什么要重写hashCode方法

    在我们平时编写Java代码时,重写equals方法时一定要重写hashCode方法,这是为什么呢? 在讨论这个问题前,我们先看下Object类中hashCode方法和equals方法. hashCod ...

  3. JavaSE——为什么重写equals的同时一定要重写hashCode?

    文章目录: 1.引出话题 2.关于equals方法 3.关于hashCode方法 4.为什么要一起重写这两个方法? 5.总结 1.引出话题 equals 方法和 hashCode 方法是 Object ...

  4. java方法的调用怎么跳出_JAVA 的一个方法调用另一个方法时,怎么把那个方法里的数据调用出来...

    例如:此例子中Calcute()方法调用dispMax()方法时,怎么把curCost的数据调用到publicListgetBidListByName1(Stringname)中来,,,谢谢大家来帮忙 ...

  5. Java中重写equals()方法时注意点

    Java中重写equals()方法时注意点 一直说,重写一个对象的equals()方法时我们必须重写HashCode()方法,但是如果我们不重写呢?会有什么影响呢? 首先看一下,什么情况下我们需要重写 ...

  6. why在重写equals时还必须重写hashcode方法

    首先我们先来看下String类的源码:可以发现String是重写了Object类的equals方法的,并且也重写了hashcode方法 public boolean equals(Object anO ...

  7. 为什么重写equals时必须重写hashCode方法?

    2019独角兽企业重金招聘Python工程师标准>>> 首先我们先来看下String类的源码:可以发现String是重写了Object类的equals方法的,并且也重写了hashco ...

  8. JAVA中重写equals()方法的同时要重写hashcode()方法

    object对象中的 public boolean equals(Object obj),对于任何非空引用值 x 和 y,当且仅当 x 和 y 引用同一个对象时,此方法才返回 true:注意:当此方法 ...

  9. JAVA中list.contains()方法,要重写equals(),hashcode()方法

    今天动力节点java培训机构小编为大家介绍"JAVA中list.contains()方法,要重写equals(),hashcode()方法",希望能够帮助正在学习java的零基础学 ...

最新文章

  1. 写单元测试应该注意什么
  2. android this context,Android應用開發中關於this.context=context的理解
  3. WINKEY功能键你会用吗??
  4. NOIP模拟测试19「count·dinner·chess」
  5. H3C的DHCP中继配置命令
  6. 伪指令endp告诉汇编程序_第2章 指令系统及汇编语言程序设计 题库和答案
  7. 扩展卢卡斯定理(Exlucas)
  8. AutoRunner 功能自动化测试项目实训之常见问题(十)
  9. Win10运行pip install image-similarity-measures失败的处理方式(GDAL和rasterio安装)
  10. Delta3D(6)教程:创建游戏角色-2
  11. 基于SSM的医院科室人员管理系统
  12. 一段代码之仿LOL移动方式
  13. 9个经典营销创业案例,彻底颠覆你的营销思维
  14. 犹他大学支付45万美元赎金以阻止被盗数据泄露
  15. string转LPCTSTR
  16. 输入身份证号和年份计算年龄
  17. 使用Java输出所有水仙花数
  18. 网络和VPC简单介绍
  19. google pinyin下如何输入英文
  20. SVN管理工具Cornerstone之:创建分支、提交合并

热门文章

  1. 超详细的APP数据指标体系分析
  2. 深度学习笔记-----YOLOV4框架结构大讲解
  3. 触发器(Trigger)
  4. 【C++篇】STL常见容器String的模拟实现
  5. 【CodeForces】896 B. Ithea Plays With Chtholly
  6. 学习:浏览器设置Burpsuite代理后打不开网页
  7. 跑步时戴什么耳机好、推荐几款专业跑步的耳机
  8. 计算机网络实验报告哈工大_哈工大计算机网络实验报告之五
  9. 数据库---主键,候选键,超键
  10. 解决linux的-bash: ./xx: Permission denied/tensorflow 运行cpu还是gpu的方法