【Java深入浅出】Map篇

【Java深入浅出】Map篇

Java中关键的Map有哪些类型?它们之间的继承关系是怎么样的?

Java中的主要map以及继承关系图如下:

这么多List、Set,他们之间肯定有很多相似跟区别,都有哪些关键的关注点呢?

它们的一些关键特点、要素汇总表如下:

在对象被作为HashMap或HashSet的key时,重写equals方法跟hashcode方法的注意事项。

上面代码的结果是null。hashMap.get(key2)获取不到k1作为key在map中的value。解析:由于Key没有重写equals方法、hashCode方法,默认使用了Object中这两个方法的定义。只有当两个对象地址相同时,equals才返回为true,hashCode返回值也才相同。(Object.hashCode方法返回对象地址)所以在这里,key1、key2逻辑上也被认为不相等,当然无法通过key2获取key1的关联value。要想让id相同的key1、key2被逻辑认为是相同的,则必须要覆盖equals方法。同时也需要覆盖hashCode方法。需满足如下约束:

规则1:当两个对象equals为true时,hashCode必须相同。

建议1:当两个对象equals为false时,hashCode建议不同,但也可以相同。(此时不同的话散列效果好、性能高)

推论1:两个对象hashCode相同时,两者equals结果不一定为true。

推论2:两个对象hashCode不同时,两者equals结果一定为false。

我们重点理解下规则1,hashMap的get(key2)方法的逻辑是,先根据key2的hashCode计算出应该到哪个桶里去找,再用key2的equals方法与桶里链表上的元素依次比较找到相同的。如果两个对象逻辑相同(equals结果为true),hashCode值不同的话,就有可能定位不到正确的桶(hashCode值%容量大小=桶的序号),导致找不到,返回null。推论2是规则1的逆否命题,所以也成立(若a则b命题成立 <==> 若非b则非a命题成立)。

HashMap 的长度为什么是2的幂次方?

一个元素究竟该从HashMap的哪个桶里存取,是通过计算hashcode值再取余计算得来的。当取余操作的除数是2的幂次方时有一个特性:取余操作 <==> 与其除数-1 的与(&)操作。机器执行二进制的&操作的效率是要远远大于取余(%)的运算效率的。length 是2的 n 次方时:hashcode%length == hashcode&(length-1)

JDK1.7 和1.8 之间, hashMap做了什么改进?

答:1.7的哈希即使冲突严重,也只会在一个点上形成的链表不断链接更多的元素,别无他法。因此1.8做了改进,如果那个点的链表长度超过TREEIFY_THRESHOLD,则会转为红黑树。提升了效率、安全性(防止恶意构造大量hash冲突的元素插入map操作内存耗尽)。

相关手记

365bet投注网 竖中指手势背后的文化内涵与情感表达解析
365bet线上网址 宏碁w700怎么样,值得入手吗?
365bet投注网 卫星互联网之频率与轨道
365bet投注网 选鞋指导|2021年,不同体重跑者跑鞋推荐指南(最舒服的跑步鞋排名)
365bet投注网 手机百度钱包在哪里 百度钱包入口介绍
365体育投注网站 中国电信天翼卡(电信卡是什么样子的?)