hashmap的生命周期(通过HashMap的源码来理解重写equals和hashcode)
hashmap的生命周期(通过HashMap的源码来理解重写equals和hashcode)其中p表示的是数组中根据hashcode运算后找出的某个具体的数组值,简单来讲就是链表第一个值。上述代码关键1处的代码是:默认情况下以下是JDK8的hashmap的源码,对此我想吐槽下:写的真是精炼,能一行写的,绝不两行写,最开始看的时候,变量哪里赋值都看了半天,实际项目编码中个人还是不推荐这种精炼的写法的,代码写出来是给大部分人读的以及后续维护的,所以性能一致或者差不多的情况下 ”可读性才是最重要的“。上述代码是JDK8关于HashMap的put的底层源码,有部分省略的地方,请注意查看”关键1”和“关键2”
这篇文章主要通过hashMap#put的源码来聊聊为什么需要同时重写hashcode和equals。
这是在某个企业面试的时候,感觉自己说的不够清楚,这里地方再总结下,希望对大家有所帮助。
额外补充一句,程序猿要晋级到工程师或者架构师,该从底层去探究的东西还是要耐心结合源码进行分析,不是仅仅看别人的总结和理论知识点就可以了,需要自己结合源码进行理解、巩固、实践。
day day up , never give up !为什么对于散列结构的数据类型,比如HashMap或者HashSet这些数据类型。若我们从业务上判定对象是表示的同一个事物,那么需要重写equals和hashcode,来保证在内存中不同的对象在业务上是一致的。
上面这话有些绕。业务上相同的但是代码层面不相同的对象,当需要hash结构进行保存的时候,就需要重写hashcode和equals方法了。默认情况下
- equals是继承自Object父类的,其中通过==进行对比。
- hashcode也是继承自Object父类的,通过native方法进行hashcode计算。
以下是JDK8的hashmap的源码,对此我想吐槽下:写的真是精炼,能一行写的,绝不两行写,最开始看的时候,变量哪里赋值都看了半天,实际项目编码中个人还是不推荐这种精炼的写法的,代码写出来是给大部分人读的以及后续维护的,所以性能一致或者差不多的情况下 ”可读性才是最重要的“。
上述代码是JDK8关于HashMap的put的底层源码,有部分省略的地方,请注意查看”关键1”和“关键2”
上述代码关键1处的代码是:
其中p表示的是数组中根据hashcode运算后找出的某个具体的数组值,简单来讲就是链表第一个值。
其中e是exsiting的缩写,表示已经存在的,该值需要在最后做判定后插入。
说回关键1处的代码:源码编写者应该是有意的通过 && 进行分割。关于&&和&的区别,我们下篇文章再谈,很有意思的一个知识点。
- 上面的判定是p.hash == hash这个很明显是判定hash值。重写hashcode的原因在这里。
- 下面的判定是(k = p.key) == key 和 (key != null && key.equals(k)),要求满足其中1个就行了。
- 前者通过==直接判定内存地址,这个判定肯定同一个对象。因为==我们是没有办法重写的。
- 后者是判定的equals,这个判定是标题提到的需要重写的equals方法。重写eqauls的原因在这里。
关键代码2处的代码也是类似的思路,请读者自行理解,不再赘述。
总结hashcode被重写是因为保证同一个业务对象在数组寻址时,落到同一个节点和对链表第一个节点进行判定。
eqauls被重写是因为需要在链表中寻找该对象是否已经存在,来判定替换或者插入。