HashMap1.7与1.8的区别

HashMap1.7与1.8的区别

1.JDK1.8主要解决或优化的问题

  1. resize 扩容优化

  2. 引入了红黑树,目的是避免单条链表过长而影响查询效率

  3. 解决了多线程死循环问题,但仍是非线程安全的,多线程时可能会造成数据丢失问题。

不同JDK1.7JDK1.8
存储结构数组+链表数组+链表+红黑树
初始化方式单独函数:inflateTable()直接集成到了扩容函数 resize() 中
hash值计算方式扰动处理 = 9次扰动 = 4次位运 算 + 5次异或运算扰动处理 = 2次扰动 = 1次位运算 + 1次异 或运算
存放数据的规则无冲突时,存放数组;冲突 时,存放链表无冲突时,存放数组;冲突 & 链表长度 < 8:存放单链表;冲突 & 链表长度 > 8: 树化并存放红黑树
插入数据方式头插法(先讲原位置的数据移 到后1位,再插入数据到该位 置)尾插法(直接插入到链表尾部/红黑树)
扩容后存储位置的计算方式全部按照原来方法进行计算 (即hashCode ->> 扰动函数 - >> (h&length-1))按照扩容后的规律计算(即扩容后的位置 =原位置 or 原位置 + 旧容量)

2.红黑树的特点

  • 结点是红色或黑色。

  • 根结点是黑色。

  • 所有叶子都是黑色。(叶子是NIL结点)

  • 每个红色结点的两个子结点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色结点)

  • 从任一节结点其每个叶子的所有路径都包含相同数目的黑色结点。

3.扩容流程图对比

 

1.8put操作

 

4.为什么在JDK1.7的时候是先进行扩容后进行插入,而在JDK1.8的时候则是先插入后进行扩容的呢?

1.7 先扩容后插入可以减少一次数据迁移

1.8 高低位的操作让迁移的成本大大降低,所以直接可以先插入在扩容(个人理解)

5.为什么在JDK1.8中进行对HashMap优化的时候,把链表转化为红黑树的阈值是8,而不是7或者不是20呢

如果选择6和8(如果链表小于等于6树还原转为链表,大于等于8转为树),中间有个差值7可以有效防止链表和树频繁转换。假设一下,如果设计成链表个数超过8则链表转换成树结构,链表个数小于8则树结构转换成链表,如果一个HashMap不停的插入、删除元素,链表个数在8左右徘徊,就会频繁的发生树转链表、链表转树,效率会很低。

还有一点重要的就是由于treenodes的大小大约是常规节点的两倍,因此我们仅在容器包含足够的节点以保证使用时才使用它们,当它们变得太小(由于移除或调整大小)时,它们会被转换回普通的node节点,容器中节点分布在hash桶中的频率遵循泊松分布,桶的长度超过8的概率非常非常小。所以作者应该是根据概率统计而选择了8作为阀值

6.哈希表如何解决Hash冲突?

 

7.HashMap的特点

 

8.为什么 HashMap 中 String、Integer 这样的包装类为 key 键?

 

9.HashMap 中的 key若 Object类型, 则需实现哪些方法?

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值