jdk1.8里面HashMap的扩容机制

链表的扩容

HashMap.Node<K,V> loHead = null, loTail = null;
HashMap.Node<K,V> hiHead = null, hiTail = null;
HashMap.Node<K,V> next;
do {
    next = e.next;
    /*为什么要和老的数组长度按位与?因为:
    数组长度都是2的幂次方,都是00000100000这种的,所以(e.hash & oldCap)的值是否为0,完全取决于oldCap里面的唯一的一个"1"
    要么是0,要么不是0
    扩容后的位置,要么在原来的位置不变,要么是oldindex+oldCap(原来的下标位置+原来的数组长度)
    */
    if ((e.hash & oldCap) == 0) {//要么在原来的位置不变
        if (loTail == null)
            loHead = e;
        else
            loTail.next = e;
        loTail = e;
    }
    else {//要么是oldindex+oldCap(原来的下标位置+原来的数组长度)
        if (hiTail == null)
            hiHead = e;
        else
            hiTail.next = e;
        hiTail = e;
    }
} while ((e = next) != null);
/*
循环结束后,再去放置到新数组上面去:
jdk1.8里面是先分组,再放置,分为低位组和高位组,要么在原来的位置不变,要么是oldindex+oldCap(原来的下标位置+原来的数组长度)
*/
if (loTail != null) {//低位组
    loTail.next = null;
    newTab[j] = loHead;
}
if (hiTail != null) {//高位组
    hiTail.next = null;
    newTab[j + oldCap] = hiHead;
}

红黑树的扩容

final void split(HashMap<K,V> map, Node<K,V>[] tab, int index, int bit) {
    TreeNode<K,V> b = this;
    // Relink into lo and hi lists, preserving order
    TreeNode<K,V> loHead = null, loTail = null;
    TreeNode<K,V> hiHead = null, hiTail = null;
    int lc = 0, hc = 0;
    //将红黑树拆分成两个链表,这里的逻辑和上面的差不多
    for (TreeNode<K,V> e = b, next; e != null; e = next) {
        next = (TreeNode<K,V>)e.next;
        e.next = null;
        if ((e.hash & bit) == 0) {
            if ((e.prev = loTail) == null)
                loHead = e;
            else
                loTail.next = e;
            loTail = e;
            ++lc;
        }
        else {
            if ((e.prev = hiTail) == null)
                hiHead = e;
            else
                hiTail.next = e;
            hiTail = e;
            ++hc;
        }
    }
    //低位的不为空,则转移低位
    if (loHead != null) {
        //小于6,则转成链表
        if (lc <= UNTREEIFY_THRESHOLD)
            tab[index] = loHead.untreeify(map);
        //否则,转成红黑树
        else {
            tab[index] = loHead;
            //如果hiHead为null,则直接整个树移过去就可以,否则还要树化低位的
            if (hiHead != null) // (else is already treeified)
                loHead.treeify(tab);
        }
    }
    if (hiHead != null) {
        if (hc <= UNTREEIFY_THRESHOLD)
            tab[index + bit] = hiHead.untreeify(map);
        else {
            tab[index + bit] = hiHead;
            if (loHead != null)
                hiHead.treeify(tab);
        }
    }
}

 

posted @ 2020-11-09 11:42  Mistolte  阅读(433)  评论(0编辑  收藏  举报