20220930-ArrayList扩容机制源码分析②

本部分对于使用设置初始容量的方法创建ArrayList集合的方式进行源码分析。

代码

public class ArrayListSource {
    public static void main(String[] args) {
        ArrayList arrayList = new ArrayList(5);  //跳转至第一步
        for (int i = 0; i < 50; i++) {
            arrayList.add(i);
        }
    }
}

底层代码

第一步:

public ArrayList(int initialCapacity) {  //initialCapacity = 5
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];  //elementData = {null, null,null,null,null}
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
}

由上ArrayList带参构造器内容可知:

  1. 当初始容量显示的设置为0时,与默认无参构造器执行方式相同,都是将elementData设置为空数组。
  2. 当初始容量大于0时,将创建一个Object类型数组,数组大小等于初始容量。
  3. 当初始容量小于0时,将抛出异常对象IllegalArgumentException

第二步:
创建完成arrayList集合之后,进入for循环,从i=0开始,执行arrayList.add(i)方法,底层代码如下:

public boolean add(E e) {  //e = 0
        modCount++;  //modCount=0,执行之后自加1
        add(e, elementData, size);  //跳转至第三步
        return true;
}

第三步:

//e = 0
//elementData = {null, null,null,null,null}
//elementData.length = 5
//s = 0
private void add(E e, Object[] elementData, int s) {
        if (s == elementData.length)  //此时if语句不成立
            elementData = grow();
        elementData[s] = e;  //elementData = {{0, null,null,null,null}
        size = s + 1;  //size = 1
}

第四步:
程序继续执行for循环,直到size=5时,表示集合中元素已经达到容量上限,程序执行第三步中的if语句,对集合进行扩容

private Object[] grow() {
        return grow(size + 1);  //size = 6,跳转至第五步
}

第五步:

//elementData.length = 5
//minCapacity = 6
private Object[] grow(int minCapacity) {
        int oldCapacity = elementData.length;  //oldCapacity = 5
        if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {  //if语句条件成立
            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)];
        }
}

第六步:

//oldLength = 5
//minGrowth = 1
//prefGrowth = 2
public static int newLength(int oldLength, int minGrowth, int prefGrowth) {
        // assert oldLength >= 0
        // assert minGrowth > 0
        int newLength = Math.max(minGrowth, prefGrowth) + oldLength;  //newLength = 7
        if (newLength - MAX_ARRAY_LENGTH <= 0) {  //if条件成立
            return newLength;  //返回第5步
        }
        return hugeLength(oldLength, minGrowth);
}

第七步:
程序执行elementData = Arrays.copyOf(elementData, newCapacity);
elementData = {0 , 1 , 2 , 3 , 4 , null , null , null}
程序继续执行for循环,当达到集合的容量上限值,继续进行扩容,扩容后的容量=原容量*1.5

posted @ 2022-09-30 07:41  淡忘的江南  阅读(38)  评论(0)    收藏  举报