JDK1.8hashmap:if (root == null || root.right == null || (rl = root.left) == null || rl.left == null)

JDK1.8hashmap:if (root == null || root.right == null || (rl = root.left) == null || rl.left == null),第1张

JDK1.8hashmap:if (root == null || root.right == null || (rl = root.left) == null || rl.left == null) 关于退化条件的理解

JDK1.8hashmap源码中,两个地方提到了退化。

在扩容的split内

如果节点个数 <= 6 个则将红黑树转为链表结构

//对lo表(表1)进行判断
    if (loHead != null) {   // 原索引位置的节点不为空
        // 如果节点个数lc<=6个则将红黑树转为链表结构
        if (lc <= UNTREEIFY_THRESHOLD)//lo表内满足退化条件
            tab[index] = loHead.untreeify(map);//将对应索引index的树变为链表
        else {
            // 将原索引位置的节点设置为对应的头节点
            tab[index] = loHead;
            //如果hiHead不为空,则代表原来的红黑树(老表的红黑树由于节点被分到两个位置)
            // 已经被改变, 需要重新构建新的红黑树
            if (hiHead != null)
                //以loHead为根节点, 构建新的红黑树
                loHead.treeify(tab);//使用链表lo变树
        }
    }

//下面同上,对hi表(表2)进行判断
    if (hiHead != null) {// 索引位置为原索引+oldCap的节点不为空
        // 如果节点个数<=6个则将红黑树转为链表结构
        if (hc <= UNTREEIFY_THRESHOLD)
            tab[index + bit] = hiHead.untreeify(map);
        else {
            //将索引位置为原索引+oldCap的节点设置为对应的头节点
            tab[index + bit] = hiHead;
            // loHead不为空则代表原来的红黑树(老表的红黑树由于节点被分到两个位置)
            // 已经被改变, 需要重新构建新的红黑树
            if (loHead != null)
                //以hiHead为根节点, 构建新的红黑树
                hiHead.treeify(tab);
        }
    }

由源码可见,退化条件使用了lc <= UNTREEIFY_THRESHOLD(6)。我暂且死记硬背将它记下,例如:当树的节点个数小于等于6个时需要进行树的退化。对吗??难说

删除树节点函数中

满足四个非空条件任意一个的树型退化。(与6无关)

// 通过root节点来判断此红黑树是否太小, 如果是则调用untreeify方法转为链表节点并返回
    if (root == null || root.right == null || (rl = root.left) == null || rl.left == null) 
    {
        tab[index] = first.untreeify(map);  // too small
        return;
    }
//使用四个非空判断,其中一个不满足非空,就需要退化,根据刚才背的退化条件:当树的节点小于等于6时需要退化。
//那么显而易见,删除一个节点后,树的结点个数明显变为了6个,需要退化。是这样的吗???

我们将满足这个判断条件的树列出观察:

//第一种树形,凑合着看吧哈哈`

//第二种树形,只包含这两种情况`

//注意第三种树形右边这颗树`

最后举了个栗子

由此可见,在树节点的删除中,退化的判断条件并非节点个数小于等于6,而是这四个非空条件所涵盖的树的形状。至于节点个数,0-10个内都有可能退化( (3)(4)中的树可证 )。

写到最后:退化这一点是我跟伙伴们在用C语言实现JDK1.8的hashmap时遇到的一些疑问与思考。还存在很多考虑不周,表达不清,甚至是知识盲区。学习过之后,简单记录一下。仅供参考。

如果有错,大家尽管指出,反正不会改!哈哈。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5696797.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存