ArrayList源码

发布时间 2023-08-01 12:35:03作者: Bright丶

add方法

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

// 添加元素
public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // 确保数组容量足够添加
    elementData[size++] = e;
    return true;
}

调用add方法往ArrayList中添加元素时,整体分为两个步骤:1、确保有足够的容量;2、把元素添加进去;所以这里的重点就是第一步了。

// 确认内置容量
private void ensureCapacityInternal(int minCapacity) {
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
// 计算容量
private static int calculateCapacity(Object[] elementData, int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    return minCapacity;
}

ensureCapacityInternal方法又分为两步,1、计算容量;2、确保容量足够;

calculateCapacity计算容量,如果是调用了ArrayList的无参构造方法的话,使用的就是DEFAULTCAPACITY_EMPTY_ELEMENTDATA,所以就会拿默认容量DEFAULT_CAPACITY和传进来的minCapacity进行比较,选择较大值作为新容量。

如果创建ArrayList时传入了容量,那么这里就是数组容量加1了。

// 确保显示容量
private void ensureExplicitCapacity(int minCapacity) {
    modCount++;

    // overflow-conscious code
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

ensureExplicitCapacity方法中首先执行了一个modCount++,这个的目的是防止并发修改,数组容量每次发生修改都要修改这个值,然后和expectedModCount进行比较,如果不一致就会触发异常。

先判断一下数组现在的容量是否小于需要的容量,如果是的会就需要扩容了,否则容量足够就不用执行操作,直接把数据存进去就行了。

private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;  // 获取现在的容量
    int newCapacity = oldCapacity + (oldCapacity >> 1);  // 扩容 变为1.5倍
    if (newCapacity - minCapacity < 0)  // 新容量还是不够
        newCapacity = minCapacity;  // 那就把容量设为新容量
    if (newCapacity - MAX_ARRAY_SIZE > 0)  // 如果容量超过了最大容量
        newCapacity = hugeCapacity(minCapacity);  // 
    // minCapacity is usually close to size, so this is a win:
    elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
    if (minCapacity < 0) // overflow
        throw new OutOfMemoryError();
    return (minCapacity > MAX_ARRAY_SIZE) ?
        Integer.MAX_VALUE :
        MAX_ARRAY_SIZE;
}