jdk1.8中HashMap的扩容,从新增第一个元素开始

置灰部分在当前场景下不考虑

1.新增第一个元素

新增第一个元素总结:

先进行数组容量初始化,初始大小为16,扩容界限为12,再找出数组对应位置,将新增的值放入。


2.继续新增元素,假设一直不产生hash冲突

 

 

 

执行完一系列操作,也就完成了数组的扩容,【注:此处还未涉及到hash冲突】

不产生hash冲突总结:

当新增的元素达到了该扩容的界限,那么会触发扩容操作,先计算扩容后的大小,也就是原数组大小的两倍,然后创建一个新容量大小的数组,再进行原数组遍历依次定位后放入新数组中。

 

非树情况下产生hash冲突总结

先确定在数组中的位置,如果该位置上已经存在元素,再判断是否key相同,如果不相同,那么获取到该位置上的尾节点,将尾节点的next指向新增的节点。当达到新增完后,发现容量大小已经超过阈值,那么开始进行扩容,扩容先产生一个原数组两倍大小的新数组,再遍历原数组,

如果遍历到的位置只有一个节点,将该节点的hash值和(新数组容量大小值-1)进行&操作定位。

如果遍历的位置是链表结构,那么依次遍历链表到末尾,期间将节点的hash和原数组容量大小进行&操作,如果高位是0,则原位置不变,如果高位是1,则新位置=(当前位置+原数组容量大小)

 

整体步骤

1.创建hashMap,

2.新增第一个元素,先进行数组容量初始化,初始化大小为16,扩容触发的阈值为12,然后将元素插入该数组中。

3.后续依次加入元素,假如新增一直没有产生hash冲突,新增完后,判断大小却达到了阈值12,那么触发数组扩容。扩容大小为原大小的2倍,也就是32,阈值扩大两倍为24。然后进行元素的重定位【但其实只是个元素的hash和(容量大小-1的值)进行与操作,这样操作的话位置不变】。

4.然后如果一直新增元素,产生hash冲突,那么先找到冲突位置的首节点,然后将新增的节点挂在尾结点,当改链路下的长度>=8,且当下的数组大小还没超过64,那么先进行扩容操作,扩容就是遍历原数组,当元素只有一个节点,则如上描述的扩容走,当元素为链表,则对元素和原数组大小进行与操作,值要么是0,要么是原数组大小,所以,要么位置不变,要么位置在原基础上加上原数组大小。

5.然后又一直加元素,加到数组容量超过了64,且其中存在的链表结构长度>=8,则进行链表转红黑树的操作。其中,红黑树在扩容的时候,碰到深度<=6的会将其转回链表

 

注:

1.扩容元素时不需要重新计算hash值

2.满足链表转红黑树的两个条件

     数组大小>=64【容易忽略这一点】

     链表长度>=8

3.红黑树什么时候转回链表

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值