Java8 ArraysList扩容过程分析

在调用add(E e)时,会调用ensureCapacityInternal(size + 1)来确保数组有足够的容量来新增元素。

    public boolean add(E e) {
        ensureCapacityInternal(size + 1); 
        elementData[size++] = e;
        return true;
    }

ensureCapacityInternal(int mincapacity)源码如下,该方法调用了calculateCapacity(elementData, minCapacity)ensureExplicitCapacity

    private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }

其中calculateCapacity(elementData, minCapacity)源码如下

    private static int calculateCapacity(Object[] elementData, int minCapacity) {
        // 调用ArrayList的无参构造函数,elementData会指向这个DEFAULTCAPACITY_EMPTY_ELEMENTDATA空数组,
        // 这时如果调用add就会进入下面这个判断
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }

如果当前数组为空数组(刚使用无参构造函数创建完ArrayList,往其添加元素时),则返回10,即最小的容量是10(刚创建完ArrayList,第一次扩容要求capacity最小是10)。
ensureExplicitCapacity(int minCapacity)源码如下,大概逻辑是:如果当前数组长度达不到想要的minCapacity,则调用grow扩容

    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;
        // 如果要求的最小容量比当前数组长度大,即当前数组长度放不下了,就会调用grow扩容
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

grow(int minCapacity)大概逻辑:计算新的数组长度,为原来数组长度的1.5倍,如果该值比要求的minCapacity小,则取minCapacity。
如果新数组长度比MAX_ARRAY_SIZE大,则调用hugeCapacity获取一个长度。
最后调用Arrays.copyOf(elementData, newCapacity)创建新数组并拷贝元素过去。
源码如下

    private void grow(int minCapacity) {
        // 旧的数组长度
        int oldCapacity = elementData.length;
        // >> 1是 右移一位,即除以2。所以这句代码意思是:newCapacity是oldCapacity的1.5倍
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        // 如果newCapacity比minCapacity还要小(刚创建完ArrayList,往其添加元素时会满足这种情况),则取minCapacity
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        // 如果newCapacity比数组最大值MAX_ARRAY_SIZE大,则调用hugeCapacity获取一个比较大的capacity
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // 创建一个newCapacity大小的新数组,并将原来数组的元素拷贝过去
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

hugeCapacity(int minCapacity)大概逻辑:如果minCapacity比MAX_ARRAY_SIZE(Integer.MAX_VALUE-8)大,则取Integer.MAX_VALUE,否则取MAX_ARRAY_SIZE。
源码如下

    private static int hugeCapacity(int minCapacity) {
        // minCapacity小于0表示溢出超过int能表示的数字范围
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        // 如果minCapacity大于MAX_ARRAY_SIZE(Integer.MAX_VALUE-8),则取nteger.MAX_VALUE,否则取MAX_ARRAY_SIZE(Integer.MAX_VALUE-8)
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

你可能感兴趣的:(Java8 ArraysList扩容过程分析)