本文为博主原创,未经允许不得转载:

1. equals 和 hashCode 方法之间的关系

  这两个方法都是 Object 的方法,意味着 若一个对象在没有重写 这两个方法时,都会默认采用 Object 类中的方法实现,它们的关系为:

  1. 如果两个对象通过equals()方法比较相等,那么这两个对象的hashCode一定相同。

  2. 如果两个对象hashCode相同,不能证明两个对象是同一个对象(不一定相等),只能证明两个对象在散列结构中存储在同一个地址(不同对象hashCode相同的情况称为hash冲突)。

2.为什么重写equals 后需要重写 hashCode

  Effective Java 第三版 中 描述为什么重写equals 方法后必须重写hashCode 方法:

每个覆盖了equals方法的类中,必须覆盖hashCode。如果不这么做,就违背了hashCode的通用约定,也就是上面注释中所说的。
进而导致该类无法结合所以与散列的集合一起正常运作,这里指的是HashMap、HashSet、HashTable、ConcurrentHashMap。

  上面注释 为 Object 类中 hashCode 方法注释:

      If two objects are equal according to the {@code equals(Object)}
* method, then calling the {@code hashCode} method on each of
* the two objects must produce the same integer result.

  结论:如果重写equals不重写hashCode它与散列集合无法正常工作。

3. 以 HashMap 为例进行论证分析

  查看 hashMap 的 put 方法

 public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}

  查看hash 方法的实现:

  static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

  查看 get 方法的实现:

   public V get(Object key) {
Node<K,V> e;
return (e = getNode(hash(key), key)) == null ? null : e.value;
}

  java中HashMap的数据结构是数组+链表+红黑树;这种数据结构,每个键值对都会被存在相应的地址中,从代码中可以看出HashMap是通过key的hashCode以及自身的容量来决定当前键值的存储索引(桶)的,确定桶的位置后,再进入桶中同时判断hashCode和equals两个方法。那也就是说,如果hashCode不同,那么HashMap就一定会创建一个新的Node键值对象。

  HashMap在put一个键值对时,会先根据键的hashCode和equals方法来同时判断该键在容器中是否已经存在,如果存在则覆盖,反之新建。所以如果我们在重写equals方法时,没有重写hashCode方法,那么hashCode方法还是会默认使用Object提供的原始方法,而Object提供的hashCode方法返回值是不会重复的(也就是说每个对象返回的值都不一样)。所以就会导致每个对象在HashMap中都会是一个新的键。

  反向论证:若一个类中重写了 equals 方法,没有重写hashCode方法;且该类的两个对象具有不同属性但 hashCode 相等,在hashMap 以该对象为键进行存储时,会出现hash冲突现象,但发现该类重写了equals 方法,且通过该类的equals 比较之后也是相等,就会出现 hashMap 中只保存了一个对象,采用get 方法获取时,就会获取到别的对象,从而导致获取对象错乱。

  

  因此 重写equals 方法必须重写 hashCode 方法,用来保证两个对象通过equals()方法比较相等,那么这两个对象的hashCode一定相同 这一原则;

java 中为什么重写 equals 后需要重写 hashCode的更多相关文章

  1. 为什么重写equals后要重写hashCode

    equals和hashCode的关系 要搞清楚题目中的问题就必须搞明白equals方法和hashCode方法分别是什么,和诞生的原因,当搞明白了这一点其实题目就不算是个问题了,下面我们来探讨分别探讨一 ...

  2. java中为什么重写equals时必须重写hashCode方法?

    在上一篇博文Java中equals和==的区别中介绍了Object类的equals方法,并且也介绍了我们可在重写equals方法,本章我们来说一下为什么重写equals方法的时候也要重写hashCod ...

  3. java中的==和equals的区别

    关于JAVA中的==和equals函数的区别 今天在研读Thinking in java 时注意到==和equals的区别,于是就通过查看JDK_API才读懂了他们的区别,于是将心得分享一下,望批评指 ...

  4. 讲解:为什么重写equals时必须重写hashCode方法

    一 :string类型的==和equals的区别: 结论:"=="是判断两个字符串的内存地址是否相等,equals是比较两个字符串的值是否相等,具体就不做扩展了,有兴趣的同学可以去 ...

  5. 为什么重写equals一定要重写hashCode?

    大家都知道,equals和hashcode是java.lang.Object类的两个重要的方法,在实际应用中常常需要重写这两个方法,但至于为什么重写这两个方法很多人都搞不明白,以下是我的一些个人理解. ...

  6. java中的==、equals()、hashCode()

    java中的==.equals().hashCode()源码分析 在java编程或者面试中经常会遇到 == .equals()的比较.自己看了看源码,结合实际的编程总结一下. 1. ==  java中 ...

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

    大家都知道,equals和hashcode是java.lang.Object类的两个重要的方法,在实际应用中常常需要重写这两个方法,但至于为什么重写这两个方法很多人都搞不明白. 下面我们看下Objec ...

  8. 2)Java中的==和equals

    Java中的==和equals   1.如果比较对象是值变量:只用==   2.如果比较对象是引用型变量:      ==:比较两个引用是不是指向同一个对象实例.      equals:       ...

  9. 为什么重写equals时必须重写hashCode方法?(转发+整理)

    为什么重写equals时必须重写hashCode方法? 原文地址:http://www.cnblogs.com/shenliang123/archive/2012/04/16/2452206.html ...

随机推荐

  1. APACHE ACTIVEMQ安装

    APACHE ACTIVEMQ安装 一.特点 支持各种语言和协议的客户端.如:Java.C.C++.C#.Ruby.Perl.Python及Php. 完全支持JMS的客户端及其他消息代理 完全支持JM ...

  2. mycat分库分表 看这一篇就够了

    ​ 之前我们已经讲解过了数据的切分,主要有两种方式,分别是垂直切分和水平切分,所谓的垂直切分就是将不同的表分布在不同的数据库实例中,而水平切分指的是将一张表的数据按照不同的切分规则切分在不同实例的相同 ...

  3. uniapp小程序图片前端压缩上传

    目录 1,前言 2,实现代码 1,前言 这次项目中做了一个图片上传,要求是大于2MB的就压缩成2MB一下的再上传,我这边利用了uniapp的文件接口,使用canvas做了一个压缩上传的功能,目前已上线 ...

  4. npm run start 后台运行

    yum provides */nohup nohup npm start & 原程序的的标准输出被自动改向到当前目录下的nohup.out文件,起到了log的作用. 停止程序   ps -ef ...

  5. vulnhub 靶机 Kioptrix Level 1渗透笔记

    靶机下载地址:https://www.vulnhub.com/entry/kioptrix-level-1-1,22/ kali ip 信息收集 先使用nmap收集目标的ip地址 nmap -sP 1 ...

  6. (stm32学习总结)—spi基本原理

    参考:spi详解   spi协议 SPI的基本介绍 SPI的简介 SPI,是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口,是Motorola首先在其M ...

  7. 【Linux-vim】vim文件:查看某几行,把某几行复制到另一个文件中

    一.查看文件的某几行1.使用cat命令(1)查看文件的前10行: cat filename |head -n 10(2)查看文件后10行: cat filename |tail -n 10(3)查看文 ...

  8. 4. Git基本工作流程

    4. Git基本工作流程 Git工作区域 向仓库中添加文件流程

  9. c语言中的字面量

    在计算机科学中,字面量(literal)是用于表达源代码中一个固定值的表示法(notation). 几乎所有计算机编程语言都具有对基本值的字面量表示,诸如:整数.浮点数以及字符串: 而有很多也对布尔类 ...

  10. Altium_Designer PCB文件的绘制(上:PCB基础和布局)

    PCB设计基础知识 PCB面板 在PCB设计中,最重要的一个面板就是"PCB面板".该面板的功能主要是对电路板中的各个对象进行精确定位,并以特定的效果显示出来.该面板还可以对各种对 ...