共同学习Java源代码-数据结构-HashMap(十九)

        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) {
                if (lc <= UNTREEIFY_THRESHOLD)
                    tab[index] = loHead.untreeify(map);
                else {
                    tab[index] = loHead;
                    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);
                }
            }

        }

这个方法是将树切分的方法

首先创建临时变量b 引用本节点

然后创建loHead loTail hiHead hiTail四个对象 代表两条链表的头和尾

然后创建lc和hc变量 代表两个链条增加的元素数

进入for循环 遍历每个节点 

进入循环后将每个节点的next置空 就是为了重新建立链表 

判断节点的哈希值和参数bit的按位与是否为0 如果为0 就将这个元素添加到loHead和loTail这个链表中 否则就放在hiHead和hiTail这个链表中 当然还会判断是否是首节点 具体的内容比较简单 不多说了

然后判断loHead不为空的话 再判断lc小于等于UNTREEIFY_THRESHOLD 也就是说 loHead的链表元素比较少 要变成链表 将新的链表放在哈希桶数组原来的下标上 如果lc大于那个阈值 就将index参数下标处赋给loHead 再判断如果hiHead不为空 说明hiHead那个链条已经树化了(注释这么说的 我也没太懂) 

对hiHead那条链表的处理大同小异 就是将这条链表放到index+bit处


        static <K,V> TreeNode<K,V> rotateLeft(TreeNode<K,V> root,
                                              TreeNode<K,V> p) {
            TreeNode<K,V> r, pp, rl;
            if (p != null && (r = p.right) != null) {
                if ((rl = p.right = r.left) != null)
                    rl.parent = p;
                if ((pp = r.parent = p.parent) == null)
                    (root = r).red = false;
                else if (pp.left == p)
                    pp.left = r;
                else
                    pp.right = r;
                r.left = p;
                p.parent = r;
            }
            return root;
        }

这个方法是左旋转的方法 参数root是根节点 参数p是要进行左旋转的节点

首先创建临时变量r pp 和rl 

判断p不为空 将p的右节点赋给r判断r不为空 也就是p有右节点

判断不成功就直接返回root了

将r的左节点 变成 p的右节点 赋给rl 也就是将要旋转的节点的右节点的左节点 替换成要旋转的节点的右节点 

将p的父节点变成r的父节点 然后赋给pp  判断pp如果为空 说明最初p节点就是根节点 这是将r变成根节点 并将r设为黑色

如果pp不为空 那么r就替代p p变成r的左节点

最后返回root

流程类似这样:



        static <K,V> TreeNode<K,V> rotateRight(TreeNode<K,V> root,
                                               TreeNode<K,V> p) {
            TreeNode<K,V> l, pp, lr;
            if (p != null && (l = p.left) != null) {
                if ((lr = p.left = l.right) != null)
                    lr.parent = p;
                if ((pp = l.parent = p.parent) == null)
                    (root = l).red = false;
                else if (pp.right == p)
                    pp.right = l;
                else
                    pp.left = l;
                l.right = p;
                p.parent = l;
            }
            return root;
        }

rotateRight方法和这个类似 不细说了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值