1.8hashmap的改进

1、数据结构

1.1、jdk1.7 使用数组+链表的结构, 链表采用的是头插法(多线程下会有形成循环链表的危险)

1.2、jdk1.8 使用数组+链表+红黑树的结构, 链表和红黑树是使用的尾插法

2、1.7 与 1.8的差别以及为什么这样设计?
2.1、在数据结构上 1.7时使用的是 数组+链表 这种数据结构,1.8时使用的是 数组+链表+红黑树 的数据结构,减少hash冲突情况下的寻址时间

2.2、在hash定位的时候, 1.7直接使用key的hash值 & n-1进行与或位运算,1.8 则先将hash进行了一次扰动处理,key的hash ^ hash>>>16位后再与 n-1 进行与运算,使hash分布更为均匀减少hash冲突

2.3、再扩容动作上 链表上的数据插入方式 从1.7头插法改为1.8的尾插法,解决了在并发情况下resize导致的链表循环指针问题

3、数据结构为什么改为 数组+链表+红黑树 呢
当每个mapentry中链表长度大于8时(且容量大于64), 会由链表转换为红黑树(减少hash冲突情况下的寻址时间复杂度 O(n)降低为O(logn)

4、为什么选择8这个临界值?

根据泊松分布,链表长度大于8的情况非常小,极大多数的情况都可以被链表的情况覆盖
在长度小于8的时候,链表和红黑树的性能相差不多,但是转化为树还需要时间和空间
当mapentery中的红黑树长度降低小于6的时候,会由红黑树转回为链表结构(6和8起到了很好的缓冲作用, 避免了频繁的数据结构转换

5、为什么选择红黑树而不是二叉树呢?

5.1、普通二叉树会出现节点分布及其不平衡的情况

5.2、AVL和平衡二叉树之间差别
AVL树更加平衡,可以提供更快的查询能力,适合查找密集形的任务
红黑树适合插入密集型任务,在插入的时候使用较少的旋转

6、为什么对hash值进行一次干扰呢
6.1、对n-1做与运算的时候,n通常比较小,n-1的二进制,大概率高位补0,这样做与运算的时候key对应hash值的前16相当于从来都不参与计算,
通过右移再进行异或的操作,使后16位具有了前16位的特征,使hash分布更为均匀

7、为什么使用尾插法
hashmap分为两步

  • 扩容:创建一个新的Entry空数组,长度是原数组的2倍。

  • ReHash:遍历原Entry数组,把所有的Entry重新Hash到新数组。

在头插法的情况下并发扩容存在链表成环的这种情况,改为尾插法避免了这种情况

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WD技术

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值