Object类中有这样一段说明,意思是建议我们equals方法和hashCode方法,或者一起重写,或者一起不重写,以维护hashCode的常规协定。

什么叫hashCode的常规协定呢?

我的理解就是:两个对象通过equals方法进行比较相等,它们分别调用hashCode方法时一定返回相同的整数;两个对象通过equals方法比较不相等是,不要求它们调用hashCode方法时必须返回不同的值,但是程序员应该意识到,在这种情况下,让它们返回不同的可以提高哈希表的性能。

怎么又涉及到哈希表的性能呢?

其实,我们一般不会直接调用hashCode方法,但是在集合中它们会被频繁的使用。重写equals方法时建议重写hashCode方法,是针对像Map、Set这种集合操作而言的。

我们创建一个类,谁都不能保证它什么时候会被放到集合中,所以,为了避免不必要的麻烦,建议重写equals方法的同时也重写hashCode方法,重写hashCode方法的同时也一起重写equals方法。

其实,equals方法与hashCode方法不一致会带来两个比较明显的问题。

一、理解困难,容易混淆

二、查找效率低下,也就是所谓的哈希表的性能会降低

这又从何说起呢?

我们知道,HashMap底层维护的是一个Entry类型的数组,向HashMap中添加键值对时,首先通过Key值计算出一个位置,该位置可能就是此元素将要放置的位置。如果发现,这个位置上没有元素,也就是为null,那么就直接将这个待添加的元素放置在该位置上。如果这个位置上已经有元素存在,那么接着通过equals方法比较这个待添加的元素Key与已经存在的这个元素的Key是否相等,不相等则执行添加操作,相等则返回旧值不执行添加操作。注意,这种情况下执行添加操作是将待添加的元素放置这个位置上,然后让这个待添加的元素指向已经存在的这个旧元素,如此在这个位置上就形成了链表。同理,取出元素是和添加类似,是通过给定对象的hashCode()方法计算出一个位置,然后在该位置上进行查找,找到就返回该元素,否则返回null。

明白了这个过程就好办了。

如果equals方法与hashCode方法一致,那么在HashMap所维护的那个Entry类型的数组中的每个位置上就只有一个元素,而不会形成链表,这样一来查找的性能就非常好,同时理解上也十分清晰明了。反之,如果二者不一致,就有可能造成难以理解或者查找的性能比较低。

下面以String类举例说明:

  • 假设String类只重写了equals()方法,而没有重写hashCode()方法。也就是说其hashCode()方法仍然继承Object类的hashCode()方法。

    看下面的代码段

HashSet set = new HashSet();

String s1 = new String("hello");

String s2 = new String("hello");

set.add(s1);

set.add(s2);

System.out.println(set.size());    //输出为2

此时,set中有两个元素,这两个元素的内容都为"hello",它们存储在数组中的不同位置上,因为

两个对象的hashCode()返回值不同。

如果我们将set中的元素迭代出来,就会看到两个"hello"。这就造成了理解上困难了,因为在我

们的记忆中set中的元素是不能重复的,但现在这个HashSet对象中却有两个"hello",这怎么解释

呢?虽然,它们实际上是两个不同的对象,但从表象上看它们确实是“一样的”,也只有构造这        个HashSet对象的我们知道,但是其它调用者却很难理解,这就是所谓的理解上的混乱。

  • 假如String类只重写了hashCode()方法,而没有重写hashCode()方法。

    同样,我们看上面那段代码

    set中仍然有两个元素,但是相对于HashMap底层的那个Entry数组来说,这两个元素在相同的位置上,并且形成了链表,s2指向s1,因为s1和s2的hashCode()返回值相同,但通过equals()方法进行比较却返回false。

    这样一来,查找起来就比较费劲了,因为要遍历链表。

    我们知道,链表遍历只能是通过前一个元素找下一个元素。

    我们这里是两个对象,找起来可能不那么费力,但是对象多了呢?链表长了呢?

这就是所谓的效率低。

这两点就造成了我们前面提到的哈希表的性能的下降。

综上所诉,虽然不强制要求重新equals方法时必须重写hashCode方法或者是重写hashCode方法必须重写equals方法,但是为了避免不必要的麻烦,建议二者要么一起重写,要么都不重写,以保持它们的一致性。

以上是作者的一点点理解,如有纰漏之处,还请多多指教。

本文转自    手不要乱摸      51CTO博客,原文链接:http://blog.51cto.com/5880861/1335139

建议重写equals方法时也一并重写hashCode方法相关推荐

  1. 为什么重写equals()就一定要重写hashCode()方法

    Object类,所有类的父类 一.为什么重写equals()方法一定要重写hashCode()方法 1.首先解释equals方法和hashcode方法分别是用来干什么的? equals()方法: 在O ...

  2. java -为什么重写equals(),还需要重写hashCode()?

    1.先post这两个方法的基本定义: equals()的定义: 浅谈Java中的equals和==(转) hashCode()的定义: java中hashCode()方法的作用 Java中hashCo ...

  3. [改善Java代码]覆写equals方法必须覆写hashCode方法

    覆写equals方法必须覆写hashCode方法,这条规则基本上每个Javaer都知道,这也是JDK API上反复说明的,不过为什么要这样做呢?这两个方法之间有什么关系呢?本建议就来解释该问题,我们先 ...

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

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

  5. java 重写equals的要点_重写equals 方法的注意事项

    java.lang.Object 中的equals方法如下 public boolean equals(Object obj) { return (this == obj); } 什么时候需要重写eq ...

  6. java重写面试题_Java面试题:重写了equals方法,为什么还要重写hashCode方法?

    核心问题:重写了equals方法,为什么还要重写hashCode方法? 这不仅仅是一道面试题,而且是关系到我们的代码是否健壮和正确的问题.在前面两篇文章涉及到了equals方法的底层讲解:<说说 ...

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

    为什么重写equals方法必须要重写hashCode方法 ​ 了解这个问题之前我们得需要知道hashCode的作用.equals方法和hashCode方法都是Object类中的基础方法,用来判断两个对 ...

  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. 基于STM32F103RE ADDA板制作
  2. 区跨链应用 | 区块链创业者不要再骗自己了
  3. python的_thread模块来实现多线程(python核心编程例子)
  4. 人脸识别之insightface开源代码使用:训练、验证、测试(4)
  5. 取消挂载点可以节省磁盘么_磁盘克隆、磁盘镜像还有复制粘贴有什么不一样?...
  6. Unity HDRP中的光照烘焙测试(Mixed Lighing )和间接光
  7. zero ecilpse下载_推荐10个免费图片下载网站,助你摆脱找图烦恼!建议收藏
  8. 软件测试--cookie学习
  9. 数学竖式排版中不为人知的技巧
  10. OpenCV 线性滤波
  11. 哈工大中文分词系统ltp4j使用总结
  12. 如何修改报表平台中数据决策系统登陆地址
  13. STM32 HAL库BH1750光强检测器驱动代码
  14. php 递归 递归方式与算法
  15. mysql导入指定数据库_mysql命令行导入sql文件到指定数据库的方法
  16. tableau自定义地图
  17. SFI立昌SHN方案与应用
  18. 《机电传动控制》第六周作业
  19. PX4代码学习系列博客(5)——在px4中添加自己的模块
  20. 好用的数据库客户端工具

热门文章

  1. Java中各种引用(Reference)解析
  2. [LOJ#6053]简单的函数 题解
  3. Recovery 流程简介
  4. 2013年1月12日学习内容
  5. WinINet function(2)Request
  6. 诗与远方:无题(七十二)
  7. Linux学习笔记(四)之用户登录
  8. 代码里配置java代理
  9. ssm中使用slf4g
  10. Jsonschema2pojo从JSON生成Java类(Maven)