宁武皇仁光九年锦文轩刻本《异闻录》载: 扶桑画师浅溪,居泰安,喜绘鲤。院前一方荷塘,锦鲤游曳,溪常与嬉戏。 其时正武德之乱,潘镇割据,战事频仍,魑魅魍魉,肆逆于道。兵戈逼泰安,街邻皆逃亡,独溪不舍锦鲤,未去。 是夜,院室倏火。有人入火护溪,言其本鲤中妖,欲取溪命,却生情愫,遂不忍为之。翌日天明,火势渐歇,人已不见。 溪始觉如梦,奔塘边,但见池水干涸,莲叶皆枯,塘中鲤亦不知所踪。 自始至终,未辨眉目,只记襟上层迭莲华,其色魅惑,似血着泪。 后有青岩居士闻之,叹曰:魑祟动情,必作灰飞。犹蛾之投火耳,非愚,乃命数也。 ————《锦鲤抄》

【为什么重写equals后还需要重写hashcode】

为什么重写equals还要重写hashcode
 
 
一些资料上都会提到,“重写equals时也要同时覆盖hashcode”;
•  先简述一下HashMap的原理
    hashmap在jdk8后采用数组+链表+红黑树的数据结构。我们通过put和get存储和获取对象。当我们给put()方法传递键和值时,先对键做一个hashCode()的计算来得到它在bucket数组中的位置来存储Entry对象。当获取对象时,通过get获取到bucket的位置,再通过键对象的equals()方法找到正确的键值对,然后在返回值对象。
 
•   HashMap存储数据的时候,是取的key值的哈希值,然后计算数组下标,再通过哈希函数计算存储地址
哈希函数构造方法有:(直接定址法,数字分析法,平方取中法,折叠法,除留余数法,随机数法等等),其中除留余数法是最常用的,也是最合理的。
如果通过哈希函数计算得出的存储地址相同,称为哈希冲突,也叫哈希碰撞,
Hash解决冲突的方法: 开放定址法,再散列函数法,链地址法。其中开放定址法又包括(主要是:线性探测法,二次探测法,伪随机探测法)
而HashMap即是采用了链地址法,也就是数组+链表的方式,
 
• 其采用链地址法解决冲突,然后进行存储;取数据的时候,依然是先要获取到哈希值,找到数组下标,然后for遍历链表集合,进行比较是否有对应的key。
  1. 无论是 put 还是 get 的时候,都需要得到key的哈希值,去定位key的数组下标;
  2. 在 get 的时候,需要调用equals方法比较是否有相等的key存储过  引用 https://www.imooc.com/article/280580?block_id=tuijian_wz

第二点解释了为什么我们需要重写equals,==只是比较地址,并不能确认是否有相同的key,不重写的话上一个 话题也提到了,会返回false,所以需要重写equals

 

那么为什么重写equals后还要重写hashcode?

由于在hashMap中在put 时,散列函数根据它的哈希值找到对应的位置,如果该位置有元素,首先会使用hashCode方法判断,如果没有重写hashCode方法,那么即使俩个对象属性相同hashCode方法也会认为他们是不同的元素(另外key值相同却被认为是不同,所以会出现相同的key,而map规定不应该出现重复key),又因为Set是不可以有重复的,所以这会产生矛盾,那么就需要重写hashCode方法

 

或者说,由于没有重写hashCode方法,所以put操作时,key(hashcode1)–>hash–>indexFor–>最终索引位置 ,而通过key取出value的时候 key(hashcode1)–>hash–>indexFor–>最终索引位置,由于hashcode1不等于hashcode2,导致没有定位到一个数组位置而返回逻辑上错误的值null。

此段引用:https://www.cnblogs.com/chengxiao/p/6059914.html

 

一句话,如果不重写hashcode方法,任何对象的hashcode值都不相等(即使逻辑上key相同,我们希望它显示相等时,结果依然是不等)

 

 

 

posted @ 2021-02-22 22:12  哒布溜  阅读(446)  评论(0编辑  收藏  举报