HashMap的resize方法的作用:在向HashMap里put元素的时候,HashMap基于扩容规则发现需要扩容的时候会调用该方法来进行扩容。
jdk1.8在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减少搜索时间。(附上结构表)
image.png
计算阈值和容量的具体代码:
image.png
总结:
1 最开始还没有元素的情况:
1.1、如果初始化的时候带了参数
(HashMap(int initialCapacity, float loadFactor)),
那么newCap就是你的initialCapacity参数 threshold就是 (int)(initialCapacity*loadFactor)
1. 2、否则就按默认的算 initialCapacity = 16,threshold = 12
2 如果已经有元素了,那么直接扩容2倍,如果
oldCap >= DEFAULT_INITIAL_CAPACITY了,那么threshold也扩大两倍
再hash代码分析:
image.png
如果e.next等于null的时候 ,说明此时并没有出现hash碰撞,所以直接通过(e.hash & (newCap - 1))计算出索引放入到新的数组中;
如果(e instanceof TreeNode)如果是树节点,(暂不分析)
e.next != null,说明e是一个多节点的链表
image.png
(e.hash & oldCap) == 0 通过hashmap的特点可以得知,hashmap的容量是2的N次幂,e.hash & oldCap==0,说明此时e.hash小于原来数组的长度,因为索引的计算方式是(e.hash & (newCap - 1)) 所以Node的索引不会发生改变,
image.png
反之新的索引值=(j + oldCap),
image.png
关于涉及到的二进制运算,则是参考了博客的一张图
image.png