阅读ArrayList源码

目录

0- 背景

1- 扩容的实现方法

(1) 有参方法

(2)无参方法

2- grow方法的功能解读

(1)首先定义变量:

(2)减少扩容次数

3- grow和newLength源码的完整源码


 

0- 背景

        阅读了JAVA中ArrayList的源码,觉得挺有意思的部分,分享给大家。

        JDK版本:1.8.0

1- 扩容的实现方法

        ArrayList扩容的核心方法为:grow方法,该方法具有两个重载方法:

(1) 有参方法

    private Object[] grow(int minCapacity) {
        int oldCapacity = elementData.length;
        if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            int newCapacity = ArraysSupport.newLength(oldCapacity,
                    minCapacity - oldCapacity, /* minimum growth */
                    oldCapacity >> 1           /* preferred growth */);
            return elementData = Arrays.copyOf(elementData, newCapacity);
        } else {
            return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
        }
    }

(2)无参方法

 private Object[] grow() {
    return grow(size + 1);
}

当调用无参方法时,会默认的再次调用有参方法,所以扩容实质上是基于有参方法实现

2- grow方法的功能解读

(1)首先定义变量:

当前需要的长度为:minCapacity;   

当前的真实长度为:oldCapacity = elementData.length;

那么,

差值为:int differValue = minCapacity - oldCapacity;

(2)减少扩容次数

       为了减少扩容次数,则每次扩容一点,可以选择扩原来长度的1.5倍,或者差值,那么为了尽可能减少扩容次数,则需要取它们的最大值,也就是源码中的newLength方法功能:

扩容之后的长度为:

int newCapacity = oldCapacity + Max.max(differValue, oldCapacity*0.5);

当然,

位运算更快,故写为:

int newCapacity = oldCapacity + Max.max(differValue, oldCapacity>>1);

        值得一提的是,之前的版本(JDK1.7)为:

int newCapacity = oldCapacity + oldCapacity>>1;

(3)如果原长度为小于等于0,或者原数组元素为空,或者则返回一个object[],长度为默认长度和所需长度的最大值(应该是为了应对直接调用grow方法)。

3- grow和newLength源码的完整源码

    private Object[] grow(int minCapacity) {
        int oldCapacity = elementData.length;
        if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            int newCapacity = ArraysSupport.newLength(oldCapacity,
                    minCapacity - oldCapacity, /* minimum growth */
                    oldCapacity >> 1           /* preferred growth */);
            return elementData = Arrays.copyOf(elementData, newCapacity);
        } else {
            return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
        }
    }

    private Object[] grow() {
        return grow(size + 1);
    }
    public static int newLength(int oldLength, int minGrowth, int prefGrowth) {
        // assert oldLength >= 0
        // assert minGrowth > 0

        int newLength = Math.max(minGrowth, prefGrowth) + oldLength;
        if (newLength - MAX_ARRAY_LENGTH <= 0) {
            return newLength;
        }
        return hugeLength(oldLength, minGrowth);
    }

ps:ArrayList其它方法都比较简单,认真的看一看源码就懂了。有时间的话,再为大家详细解读一下。 

码字不易 谢谢你的点赞 ^_^

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值