扩容:

void resize(int newCapacity){
   
    Entry [] oldTavle = table;
    int oldCapacity = oldTable.length;
    if(oldCapacity == MAXIMUM_CAPACITY){
   
        threshold = Integer.MAX_VALUE;
        return;
    }
    Entry [] newTable = new Entry[newCapacity];
    transfer(newTable,initHashSeedAsNeeded(newCapacity));//将老的数组中的元素转移到新的数组中
    table = newTable;
    threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);
    }
}

转移

void transfer(Entry[] newTable,boolean rehash){
   
    int newCapacity = newTable.length;
    for(Entry<K,V> e : table){
   
        while(null != e){
   
            Entry<K,V> next = e.next;
            if(rehash){
   
            //得到hash值
                e.hash = null == e.key ? 0 : hash(e.key);
            }
            //重新计算数组索引
            int i = indexFor(e.hash,newCapacity);
            e.next = newTable[i];
            newTable[i] = e;
                e = next;
        }
    }
}

核心代码

void transfer(Entry[] newTable,boolean rehash){
   
    int newCapacity = newTable.length;
    //循环就的table数组
    for(Entry<K,V> e : table){
   
    //判断当前位置下的结点,并移动
        while(null != e){
   
            Entry<K,V> next = e.next;
            e.next = newTable[i];
            newTable[i] = e;
                e = next;
        }
    }
}

核心代码图解

<mark>在单线程时:</mark>

------------------------------------------- 以上是while循环的第一次完成-------------------------------------------

------------------------------------------- 以上是while循环的第二次完成-------------------------------------------
再次判断e==null,所以跳出while循环

------------------------------------------- 以上是最终在新的数组中的样子------------------------------------------

<mark>在多线程时:(会出现环形链表)</mark>

由于线程1挂起,线程2操作(线程2的操作可以参照在单线程的操作)得到下图结果

当线程2操作完成后线程1醒了,又开始了挂起之后的操作:



------------------------------------------- 执行完成发现形成了循环链表------------------------------------------


------------------------------------------- 以上是最终在新的数组中的样子------------------------------------------