java8-HashMap-resize()详细原理

//数组扩容
final HashMap.Node<K, V>[] resize()
{

    //临时数组
    HashMap.Node<K, V>[] oldTab = table;
    //现在的hash表容量,第一次初始化时为0
    int oldCap = (oldTab == null) ? 0 : oldTab.length;
    //现在的扩容临界值
    int oldThr = threshold;
    //新的容量,新的阈值
    int newCap, newThr = 0;
    //hash表容量不为0时
    if (oldCap > 0) {
        //如果hash表容量已达到最大临界值,则返回原数组,并且扩容临界值保持不变,否则,
        // 数组扩容一倍且扩容后的表不能大于限制值,将扩容临界值(该临界值还未乘以加载因子)翻倍
        if (oldCap >= MAXIMUM_CAPACITY) {
            threshold = Integer.MAX_VALUE;
            return oldTab;
        } else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
                oldCap >= DEFAULT_INITIAL_CAPACITY)
            newThr = oldThr << 1; // double threshold
    } else if (oldThr > 0) // 容量用阈值
        newCap = oldThr;
    else {           //第一次创建,使用默认值生成相关参数
        newCap = DEFAULT_INITIAL_CAPACITY;
        newThr = (int) (DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
    }
    //第一次扩容初始化阈值
    if (newThr == 0) {
        float ft = (float) newCap * loadFactor;
        newThr = (newCap < MAXIMUM_CAPACITY && ft < (float) MAXIMUM_CAPACITY ?
                (int) ft : Integer.MAX_VALUE);
    }
    //更新扩容临界值
    threshold = newThr;
    //创建hash表
    @SuppressWarnings({"rawtypes", "unchecked"})
    HashMap.Node<K, V>[] newTab = (HashMap.Node<K, V>[]) new HashMap.Node[newCap];
    table = newTab;
    //已存在hash表
    if (oldTab != null) {
        //遍历hash表中每个桶
        for (int j = 0; j < oldCap; ++j) {
            //临时节点变量,指向旧桶中的节点元素
            HashMap.Node<K, V> e;
            //如果旧的hash表的当前桶位置存在节点,将值赋值于e
            if ((e = oldTab[j]) != null) {
                //另该桶的值为null
                oldTab[j] = null;
                //如果取出来的节点不存在下一个元素,则重新计算对应新hash桶的位置
                if (e.next == null)
                    newTab[e.hash & (newCap - 1)] = e;
                else if (e instanceof HashMap.TreeNode)  //红黑树
                    ((HashMap.TreeNode<K, V>) e).split(this, newTab, j, oldCap);
                else { // 链表
                    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; //指向下一个节点

                        //判断当前节点的hash值的比hash表容量高一位的二进制位是否为1,如果为0,则节点保持原桶,如果为1,到新桶
                        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; //当前桶位置+旧的hash表容量
                    }
                }
            }
        }
    }
    return newTab;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值