置灰部分在当前场景下不考虑
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.红黑树什么时候转回链表