在我们平时编写Java代码时,重写equals方法时一定要重写hashCode方法,这是为什么呢?

在讨论这个问题前,我们先看下Object类中hashCode方法和equals方法。

hashCode方法:

翻译如下:

equals方法:

翻译如下:

1、hashCode方法的作用

在Java中也一样,hashCode方法的主要作用是为了配合基于散列的集合一起正常运行,这样的散列集合包括HashSet、HashMap以及HashTable。

为什么这么说呢?考虑一种情况,当向集合中插入对象时,如何判别在集合中是否已经存在该对象了?

也许大多数人都会想到调用equals方法来逐个进行比较,这个方法确实可行。但是如果集合中已经存在一万条数据或者更多的数据,如果采用equals方法去逐一比较,效率必然是一个问题。

此时hashCode方法的作用就体现出来了,当集合要添加新的对象时,先调用这个对象的hashCode方法,得到对应的hashcode值,实际上在HashMap的具体实现中会用一个table保存已经存进去的对象的hashcode值,如果table中没有该hashcode值,它就可以直接存进去,不用再进行任何比较了;如果存在该hashcode值, 就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址,所以这里存在一个冲突解决的问题,这样一来实际调用equals方法的次数就大大降低了,说通俗一点:Java中的hashCode方法就是根据一定的规则将与对象相关的信息(比如对象的存储地址,对象的字段等)映射成一个数值,这个数值称作为散列值。

java.util.HashMap的中put方法的具体实现,先计算key的hash值,从table数组中取出对应节点,如果节点不存在则添加一个节点;如果存在则更新value,返回旧value。

hash方法会调用对象的hashCode()方法:

addEntry方法添加新节点:

new一个Entry实例,next指向原有的Entry实例。也就是新new的Entry实例是该链表的头。

Entry是一个静态内部类,有一个属性next,指向下一个Entry,形成一个链表结构。

2、equals方法和hashCode方法

看下面代码:

输出结果:

我们Student类重写了equals方法,hashCode方法没有重写,s1和s2的姓名和年龄相同,equals方法为true,认为是同一个人。但是s1和s2的hashCode返回不同。

我们看下hashMap的get方法,先获取key的hashCode,由于s1和s2的hashCode不同,所以hashMap.get(s2)得到的是null。

接下来我们重写下Student类的hashCode方法,让equals方法和hashCode方法始终在逻辑上保持一致性。

重新运行,输出结果如下,s1和s2的hashCode相同了,hashMap.get(s2)得到了1。

① 在 Java 应用程序执行期间,在对同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是将对象进行 equals 比较时所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。

② 如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果。

③ 如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么对这两个对象中的任一对象上调用 hashCode 方法不 要求一定生成不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。

如果hashCode方法依赖于对象中易变的数据,用户就要当心了,因为此数据发生变化时,hashCode()方法就会生成一个不同的hash值。看下面例子:

修改了age属性的值,导致hashCode变化,所以输出为“null”。

因此,在设计hashCode方法和equals方法的时候,如果对象中的数据易变,则最好在equals方法和hashCode方法中不要依赖于该字段。

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

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

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

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

    在每个类中,在重写equals方法的时侯,一定要重写hashcode方法. 根据Object规范,规范约定: 如果两个对象通过equals方法比较是相等的,那么它们的hashCode方法结果值也是相等 ...

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

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

  4. java jar 源码乱码,java使用jar包时出现乱码的解决方法

    java使用jar包时出现乱码的解决方法 发布时间:2020-06-17 17:06:29 来源:亿速云 阅读:105 作者:元一 jar包是什么: jar(Java Archive,Java归档文件 ...

  5. java中equals函数所在的类,重写Java中的equals方法介绍

    Java中,只有8种基本类型不是对象,例如:4种整形类型(byte, short, int,long),2种浮点类型(flout, double),boolean, char不是对象,其他的所有类型, ...

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

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

  7. Java读取properties配置文件时,中文乱码解决方法

    转载自 关于java.util.Properties读取中文乱码的正确解决方案(不要再用native2ascii.exe了) 碰到了用java.util.Properties读取中文内容(UTF-8格 ...

  8. java清除运行窗口内容,Java实现软件运行时启动信息窗口的方法

    本文实例形式详述了Java实现一个程序运行时的启动窗口效果,如常用的Microsoft Word. Borland JBuilder 等,这样的窗口称为信息窗口.使用信息窗口的好处是可以使用户在等待软 ...

  9. Java获取MP3文件时长的几种方法

    在网上找了很多方法,其中最匮乏的就是获取网络资源音频的时长,在这里总结一下: 1:获取网络资源音频时长: 这种方法是获取文件字节大小然后在用公式自己算的 BufferedInputStream bis ...

最新文章

  1. php内置常用函数是哪些,PHP常用函数有哪些
  2. linux 修改时区_如何在 Ubuntu 20.04 上设置或者修改时区
  3. GridSearchCV.grid_scores_和mean_validation_score报错
  4. new chosen courses at ifm
  5. linux go 安装路径,在Alpine Linux D的路径中找不到已安装的Go二进制文件
  6. 一文读懂云计算和PAYG“现付现用”模型
  7. HTML右下角音乐播放器,利用HTML5实现网页底部音乐播放器代码
  8. 音阶频率对照表_【乐理知识】音符与休止符时值对照表(建议收藏)
  9. 微信 JS-SDK 说明文档
  10. 深度学习李宏毅21春_16_GAN_P3
  11. 简单图片木马的生成与利用
  12. python和java哪个好就业-计算机专业选Java和Python哪个前景好点?
  13. 5月3日云栖精选夜读:乾隆会判阿尔法狗死刑吗 ——浅谈当前人工智能的技术进化...
  14. 微型计算机原理与接口技术(周荷琴 冯焕清)第六版 课后习题答案 第一章(部分答案)
  15. vs2013 与mysql的连接数据库_VS2013连接Mysql数据库的设置以及常见问题
  16. pytorch学习(五)---torch.nn模块
  17. [PyQt] Python界面编程学习总结
  18. ISO/IEC 27018 中文版
  19. 中国电信与联通合作,期待的只是一场翻身仗?
  20. 合肥市第 34 届青少年信息学(计算机)奥林匹克竞赛小学组试题

热门文章

  1. 计算机boot进入u盘启动,暗影精灵5怎么设置u盘启动 暗影精灵5设置u盘启动方法...
  2. Java PipedInputStream available()方法与示例
  3. java 根据类名示例化类_Java类类的requiredAssertionStatus()方法和示例
  4. 改jpg_|我来改第04期|—人物海报设计
  5. 对cookie与session的理解
  6. 硬件nat关闭还是开启_超能课堂(173):AfterBurner不止超频,还是绝佳的游戏伴侣...
  7. java settime_Java日历setTime()方法及示例
  8. expm1_Java Math类静态double expm1(double d)及其示例
  9. 消息队列终极解决方案——Stream(下)
  10. 面试官:谈谈数据库连接池的原理