通过优锐课核心java学习笔记中,我们可以看到,码了很多专业的相关知识, 分享给大家参考学习。
HashMap的底层数据结构是数组+链表+红黑树,我们知道数组的长度是固定的,所以涉及到扩容的概念,在HashMap中resize()方法就是完成这项工作的。
resize()方法有两个主要的作用:
1:初始化底层数组table
2:进行扩容
接下来我们从源码角度分析以下:
第一段:映入眼帘的是获取当前的数组和扩容的阀门
//把当前底层数组赋值给oldTab
Node<K,V>[] oldTab = table;
//获取当前数组的大小oldCap
int oldCap = (oldTab == null) ? 0 : oldTab.length;
//获取扩容的阀门
int oldThr = threshold;
int newCap, newThr = 0;
第二段:映入眼帘的是条件判断语句,判断是初始化数组还是扩容。
if (oldCap > 0) {
//走到这一步:说明数组已经被初始化了
if (oldCap >= MAXIMUM_CAPACITY) {
//走到这一步:说明底层数组的长度已经是最大的了。
threshold = Integer.MAX_VALUE;
return oldTab;
}
else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
oldCap >= DEFAULT_INITIAL_CAPACITY)
//走到这一步:说明数组的长度扩展到原来的2倍,阀门threshold扩展到原来的2倍。
newThr = oldThr << 1; // double threshold
}
else if (oldThr > 0) // initial capacity was placed in threshold
//走到这一步:说明调用HashMap的有参构造函数,因为无参构造函数并没有对threshold进行初始化。
newCap = oldThr;
else { // zero initial threshold signifies using defaults
//走到这一步:说明调用的无参构造函数
newCap = DEFAULT_INITIAL_CAPACITY;
newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
}
对上面的第二段代码进行总结如下:
1:如果已经对底层数组进行了初始化,则进行扩容,
1.1:如果当前数组的长度已经最大的整数值了,就最大值赋值给threshold.
1.2:如果没有达到最大的整数值,则把数组长度扩展到原来的两倍,把阀门threshold扩展到原来的两倍
2:如果调用了HashMap(int initialCapacity, float loadFactor)或者HashMap(int initialCapacity),这两个构造函数都会初始化threshold,所以oldThr=threshold>0,会进入此条件