ArrayList 扩容机制分析

ArrayList 扩容机制分析

注意:文章内容基于 JDK 8,其他版本的 JDK 可能会存在差异。

构造函数

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

public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

public ArrayList(Collection<? extends E> c) {
    Object[] a = c.toArray();
    if ((size = a.length) != 0) {
        if (c.getClass() == ArrayList.class) {
            elementData = a;
        } else {
            elementData = Arrays.copyOf(a, size, Object[].class);
        }
    } else {
        // replace with empty array.
        elementData = EMPTY_ELEMENTDATA;
    }
}
private static final int DEFAULT_CAPACITY = 10;
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[] elementData;
private int size;

默认无参构造函数,初始化容量为 10,初始化为空数组,当添加第一个元素时,数组的容量才变成 10。

带容量参数的构造函数,用户可以在初始化 ArrayList 对象时,指定初始化容量大小,如果传入的参数大于0,则创建指定大小的数组,如果传入的参数等于 0,则初始化为空数组,如果传入的参数小于 0,则抛出异常。

add 函数

public boolean add(E e) {
    // 确保数组容量符合要求
    ensureCapacityInternal(size + 1);
    elementData[size++] = e;
    return true;
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
    // 如果是默认容量,则返回默认容量和最小容量的较大者
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    return minCapacity;
}

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

private void ensureExplicitCapacity(int minCapacity) {
    modCount++;
    // 判断是否需要对数组进行扩容
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

grow 函数

private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8
// 扩容
private void grow(int minCapacity) {
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    elementData = Arrays.copyOf(elementData, newCapacity);
}

int newCapacity = oldCapacity + (oldCapacity >> 1);

新的容量为原来容量的 1.5 倍左右,如果新的容量小于最小需要的容量,则新的容量为最小需要的容量,如果新的容量大于MAX_ARRAY_SIZE,则调用hugeCapacity函数。

hugeCapacity 函数

private static int hugeCapacity(int minCapacity) {
    if (minCapacity < 0)
        throw new OutOfMemoryError();
    return (minCapacity > MAX_ARRAY_SIZE) ?
        Integer.MAX_VALUE :
        MAX_ARRAY_SIZE;
}

比较 minCapacityMAX_ARRAY_SIZE,如果 minCapacity 大于最大容量,则新容量则为Integer.MAX_VALUE,否则,新容量大小则为 MAX_ARRAY_SIZE 即为 Integer.MAX_VALUE - 8

总结

ArrayList 的底层是数组,相当于动态数组,和 Java 中的数组相比,它的容量可以动态增长,每次扩容时新的容量为原来容量的 1.5 倍左右。


ArrayList 扩容机制分析
https://liuyuhe666.github.io/2025/03/03/ArrayList-扩容机制分析/
作者
Liu Yuhe
发布于
2025年3月3日
许可协议