JDK1.8---HashMap的resize()扩容方法源码详解
resize()方法触发时机
首先总结一下JDK1.8的HashMap都在什么时候触发resize()方法,根据阅读源码总结了三个时机触发扩容,这里只做介绍,后面根据源码详细分析
HashMap是由数组+链表+红黑树构成的,数组就称之为桶了
①众所周知当HashMap的使用的桶数达到总桶数*加载因子的时候会触发扩容;
②当某个桶中的链表长度达到8进行链表扭转为红黑树的时候,会检查总桶数是否小于64,如果总桶数小于64也会进行扩容;
③当new完HashMap之后,第一次往HashMap进行put操作的时候,首先会进行扩容。原理会在下面根据源码分析,这里先做个例子并思考一下原因,下面分析完自然懂得原因。
首先思考一个问题:为何new出来HashMap的时候并没有报OOM,而是在第一次进行put操作的时候才报的OOM?
为了更好的分析扩容首先我们先看一下HashMap带参数的构造函数
这里的this.threshold本应该指的是HashMap的下次扩容的阈值,仔细看你会发现这里并没有对组成HashMap的数组按你写的大小进行初始化,而是把你的参数赋值给下次的扩容的阈值。这也就解决了上一个问题出现的原因,当第一次put值的时候会对这个数组是否初始化进行检测,如果没有初始化会先触发resize方法,那么什么时候才真正对其初始化的呢,请看下面分析
再看一下tableSizeFor函数
这个函数是用来对你申请的容量进行处理让他变成最接近你申请的容量的2次幂的大小,这里注意:假如你申请的容量为0,最后处理的结果会变成1,代表着你最小的容量为1
下面开始根据源码介绍HashMap的扩容原理
首先看一下resize()源码,可以先不用读,看我下面分析再返回源码看我提的重要的位置
1 final Node<K,V>[] resize() {
2 Node<K,V>[] oldTab = table;
3 int oldCap = (oldTab == null) ? 0 : oldTab.length;
4 int oldThr = threshold;
5 int newCap, newThr = 0;
6 if (oldCap > 0) {
7 if (oldCap >= MAXIMUM_CAPACITY) {
8 threshold = Integer.MAX_VALUE;
9 return oldTab;
10 }
11 else if (