JDK1.8源码 resize()解析

final HashMap.Node<K,V>[] resize() {
        HashMap.Node<K,V>[] oldTab = table;
        int oldCap = (oldTab == null) ? 0 : oldTab.length;
        int oldThr = threshold;	//threshold在table未初始化时存储的是构造方法中tableSizeFor(initialCapacity)的值,如果未带参数initialCapacity,则是0;**tableSizeFor()方法不懂可以看之前的博客**
        int newCap, newThr = 0;
        if (oldCap > 0) {		//HashMap中添加过元素的情况下oldCap才会大于0,否则未初始化oldTab==null,oldCap==0;
            if (oldCap >= MAXIMUM_CAPACITY) {	//原来的容量大于等于HashMap最大容量,给临界值赋值为一个四位整型的最大值,大约为MAXIMUM_CAPACITY的两倍(MAXIMUM_CAPACITY=2^30=1073741824,Integer.MAX_VALUE=2147483647)
                threshold = Integer.MAX_VALUE;
                return oldTab;
                //这段代码整体意思就是  因为添加过元素之后,临界值是容量的0.75倍,达到这个值就会扩容,因为容量已经达到最大,所以给临界值设置一个达不到的值,为的就是以后再进行添加元素时,不会再扩容;
            }
            else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
             oldCap >= DEFAULT_INITIAL_CAPACITY)	//添加过元素的扩容,直接容量和临界值扩大两倍
                newThr = oldThr << 1; // double threshold
        }
        else if (oldThr > 0) // initial capacity was placed in threshold
            newCap = oldThr;	//未添加元素的时,进行初始化,因为oldThr=threshold存储的是构造方法中tableSizeFor(initialCapacity)的值,所以这里newCap得到的值是初始化容量大小
        else {               // zero initial threshold signifies using defaults
            newCap = DEFAULT_INITIAL_CAPACITY;
            newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
            //未调用initialCapacity的有参构造方法,进行默认大小赋值
        }
        if (newThr == 0) {	//当上述代码执行第二个条件语句时,newThr未进行赋值,所以在这里赋值;
            float ft = (float)newCap * loadFactor;
            newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
             (int)ft : Integer.MAX_VALUE);
             //其实就是容量newCap的0.75倍
        }
        threshold = newThr;//重新给临界值赋值,第一次调用resize()过后都不在存储初始容量
        @SuppressWarnings({"rawtypes","unchecked"})
        HashMap.Node<K,V>[] newTab = (HashMap.Node<K,V>[])new HashMap.Node[newCap];
        table = newTab;
        if (oldTab != null) {	//把oldTab上的元素移动到newTab上
            for (int j = 0; j < oldCap; ++j) {
                HashMap.Node<K,V> e;
                if ((e = oldTab[j]) != null) {//遍历oldTab
                    oldTab[j] = null;
                    if (e.next == null)//如果oldTab[j]上只存在一个节点,直接挂到newTab上
                        newTab[e.hash & (newCap - 1)] = e;//[e.hash & (newCap - 1)]计算下标,不懂可参考之前的博客
                    else if (e instanceof TreeNode)//如果是树节点,则进行树处理,有点复杂,不展开多讲,有兴趣自己去了解。嘻嘻~
                        ((HashMap.TreeNode<K,V>)e).split(this, newTab, j, oldCap);
                    else { // preserve order	这里是对oldTab[j]存在不止一个节点时,进行处理
                        HashMap.Node<K,V> loHead = null, loTail = null;//这两个节点是维护一个位置未发生变化的链表(维护oldTab[j]下位置不变的节点)
                        HashMap.Node<K,V> hiHead = null, hiTail = null;//这两个节点是维护一个位置发生变化的链表(维护oldTab[j]下位置变化的节点)
                        //因为原来的元素位置可能保持不变,可能是原来位置加上原来的oldTab长度:
                        //hash(不变情况):	 0000 0000 0000 0010	
                        //oldCap(16)-1:    	 0000 0000 0000 1111
                        //newCap(32)-1:      0000 0000 0001 1111
                        //hash(变化情况):	 0000 0000 0001 0010
                        //按位与运算,我们可以明显的看出,不变情况的两种计算的结果是[2],而位置变化情况两种计算结果分别是[2],[18];	
                        HashMap.Node<K,V> next;
                        do {
                            next = e.next;
                            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;//直接把维护位置不变的链表头结点挂在newTab[j]上
                        }
                        if (hiTail != null) {
                            hiTail.next = null;
                            newTab[j + oldCap] = hiHead;//直接把维护位置变化的链表头结点挂在newTab[j + oldCap]上
                        }
                    }
                }
            }
        }
        return newTab;
    }

啃源码不易,有收获的小伙伴点个赞哦~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值