resize
final Node<K,V>[] resize() {
// oldTab引用扩容前的哈希表
Node<K,V>[] oldTab = table;
// 扩容前长度 如果扩容前hash表是null(刚刚初始化好) 那么就=0
// 否则就是 扩容前hash表的长度
int oldCap = (oldTab == null) ? 0 : oldTab.length;
// 扩容前的 扩容阈值
int oldThr = threshold;
// 新长度 新扩容阈值
int newCap, newThr = 0;
// 如果扩容前大小>0 表明这是已经初始化过的hashMap
if (oldCap > 0) {
// 如果扩容前容量已经≥了最大值
if (oldCap >= MAXIMUM_CAPACITY) {
// 给扩容阈值设置一个很大的数
threshold = Integer.MAX_VALUE;
// 直接返回 ,不能再扩容了
return oldTab;
}
// 正常的扩容
// 将扩容前大小左移一位 *2 赋给 新大小
// 如果新大小<最大值 并且扩容前大小>16
// 就把旧扩容阈值放大两倍
else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
oldCap >= DEFAULT_INITIAL_CAPACITY)
// ?? 这里为什么要大于等于16 才左移 而小于16 时 要到最下面 计算
newThr = oldThr << 1; // double threshold
}
// 没有初始化过的 hashMap
// 并且oldThr>0
// 情况1 :new HashMap(initCap,loadFactor) 如果传入8 oldThr就是8 如果4 就是4
// 如果传9 就是16
// 情况2 :new HashMap(initCap) 和情况1一样
// 情况3 :new HashMap(map) 并且map有数据
else if (oldThr > 0) // initial capacity was placed in threshold
// 把旧阈值赋给新大小
// 如果是以上三种情况 那么旧阈值其实就是数组的大小
// 又因为当前没有初始化 那么直接将旧阈值赋给新大小即可
newCap = oldThr;
// 没有初始化过 并且oldThr=0
// 情况:没有赋初值的初始化
else { // zero initial threshold signifies using defaults
// 新大小 直接为 16默认值
newCap = DEFAULT_INITIAL_CAPACITY;
// 新阈值为 16*0.75 = 12
newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
}
// 如果新阈值=0
// 在上述几种情况中
// 没有初始化过hashMap 并且在new HashMap时 有传入大小
// 那么新的阈值就没有处理 而是0
// 另外一种是:已经初始化过了 但是旧的容量没有超过16
if (newThr == 0) {
// 新阈值=新大小*0.75
float ft = (float)newCap * loadFactor;
newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
(int)ft : Integer.MAX_VALUE);
}
threshold = newThr;
// 扩容操作
@SuppressWarnings({"rawtypes","unchecked"})
// 创建了一个新数组
// 也有可能是第一次创建数组
Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
table = newTab;
// 说明扩容前已经有数据了 而不是第一次创建数组
if (oldTab != null) {
// 循环处理旧数组中的每一个
for (int j = 0; j < oldCap; ++j) {
// 当前Node节点
Node<K,V> e;
// 如果当前节点不是null
// 但是数据的具体是单个数据,还是链表,还是红黑树并不知道
if ((e = oldTab[j]) != null) {
// 首先将原来的设为null 方便垃圾回收
oldTab[j] = null;
// 如果e.next为空 说明这就是一个单独的元素 没有链表也没有树
if (e.next == null)
// 重新寻址 赋值
newTab[e.hash & (newCap - 1)] = e;
// 如果是树
else if (e instanceof TreeNode)
((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
// 如果是桶位已经形成链表
else { // preserve order
// 低位链表 16—》32 索引15的哪个位置
Node<K,V> loHead = null, loTail = null;
// 高位链表 16—》32 索引31的哪个位置
Node<K,V> hiHead = null, hiTail = null;
Node<K,V> next;
// 这个do-while循环相当于在原来的链表上做了一个拆分的工作
// 然后将拆分好的两个链表 赋给 低位和高位
// do while循环
// e 是 旧桶位第一个node
do {
next = e.next;
// 例子:16——》32
// 原来在15中的数据有两种
// .... 1 1111
// .... 0 1111
// 那么& 10000
// 就只会出现 0 和 1 两种结果
// 如果是0 就放在低位
if ((e.hash & oldCap) == 0) {
if (loTail == null)
loHead = e;
else
loTail.next = e;
loTail = e;
}
else {
if (hiTail == null)
hiHead = e;
else
hiTail.next = e;
hiTail = e;
}
} while ((e = next) != null);
// 截断
if (loTail != null) {
loTail.next = null;
newTab[j] = loHead;
}
// 截断
if (hiTail != null) {
hiTail.next = null;
newTab[j + oldCap] = hiHead;
}
} // 如果是链表
} // 如果不是空
} // for
}
return newTab;
}