HashMap-split()方法源码简读(JDK1.8)

//红黑树转回链表的阈值
static final int UNTREEIFY_THRESHOLD = 6;

 /** 这个方法在HashMap进行扩容时会调用到:  ((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
  * @param map 代表要扩容的HashMap
  * @param tab 代表新创建的数组,用来存放旧数组迁移的数据
  * @param index 代表旧数组的索引
  * @param bit 代表旧数组的长度,需要配合使用来做按位与运算
  */
  final void split(HashMap<K,V> map, Node<K,V>[] tab, int index, int bit) {
            //做个赋值,因为这里是((TreeNode<K,V>)e)这个对象调用split()方法,所以this就是指(TreeNode<K,V>)e对象,所以才能类型对应赋值
            TreeNode<K,V> b = this;
            //设置低位首节点和低位尾节点
            TreeNode<K,V> loHead = null, loTail = null;
            //设置高位首节点和高位尾节点
            TreeNode<K,V> hiHead = null, hiTail = null;
            //定义两个变量lc和hc,初始值为0,后面比较要用,他们的大小决定了红黑树是否要转回链表
            int lc = 0, hc = 0;
            //这个for循环就是对从e节点开始对整个红黑树做遍历,如果对这循环赋值略有不懂,可以参考这篇模仿的博客@1
            for (TreeNode<K,V> e = b, next; e != null; e = next) {
                //取e的下一节点赋值给next遍历
                next = (TreeNode<K,V>)e.next;
                //取好e的下一节点后,把它赋值为空,方便GC回收
                e.next = null;
                //以下的操作就是做个按位与运算,按照结果拉出两条链表,具体的操作可以参考这篇博客@2
                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;
                }
            }
            
            //如果低位链表首节点不为null,说明有这个链表存在
            if (loHead != null) {
                //如果链表下的元素小于等于6
                if (lc <= UNTREEIFY_THRESHOLD)
                    //那就从红黑树转链表了,低位链表,迁移到新数组中下标不变,还是等于原数组到下标
                    tab[index] = loHead.untreeify(map);
                else {
                    //低位链表,迁移到新数组中下标不变,还是等于原数组到下标,把低位链表整个拉到这个下标下,做个赋值
                    tab[index] = loHead;
                    //如果高位首节点不为空,说明原来的红黑树已经被拆分成两个链表了
                    if (hiHead != null)
                        //那么就需要构建新的红黑树了
                        loHead.treeify(tab);
                }
            }
            //如果高位链表首节点不为null,说明有这个链表存在
            if (hiHead != null) {
                 //如果链表下的元素小于等于6
                if (hc <= UNTREEIFY_THRESHOLD)
                    //那就从红黑树转链表了,高位链表,迁移到新数组中的下标=【旧数组+旧数组长度】
                    tab[index + bit] = hiHead.untreeify(map);
                else {
                    //高位链表,迁移到新数组中的下标=【旧数组+旧数组长度】,把高位链表整个拉到这个新下标下,做赋值
                    tab[index + bit] = hiHead;
                    如果低位首节点不为空,说明原来的红黑树已经被拆分成两个链表了
                    if (loHead != null)
                        //那么就需要构建新的红黑树了
                        hiHead.treeify(tab);
                }
            }
        }

博客@1:模仿HashMap-split()方法中的for循环,方便理解
博客@2:关于按位与运算为什么能根据高低位拆分出两条链表,可以参考博客:HashMap的扩容机制(JDK1.8)

  • 7
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值