Source code analysis of adding and removing elements of ArrayList

1 Add elements

ArrayList is based on array storage. The default array size is 10. When the capacity of adding elements is not enough, the capacity will be expanded. For the following code:

// 创建一个 ArrayList 对象
ArrayList<Integer> nums = new ArrayList<>();
// 向集合中添加元素
nums.add(1);
nums.add(2);
nums.add(3);

When executing new ArrayList(), call the ArrayList no-argument constructor

public ArrayList() {
    // DEFAULTCAPACITY_EMPTY_ELEMENTDATA 是一个空的 Object 类型的数组,当添加第一个元素时,elementData 指向一个大小为 10 的数组
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

When the add() method is called

public boolean add(E e) {
    // 当前元素个数+1,判断是否需要进行扩容操作
    ensureCapacityInternal(size + 1);
    // 将此元素添加到数组
    elementData[size++] = e;
    return true;
}

ensureCapacityInternal 方法

 private void ensureCapacityInternal(int minCapacity) {
     // 当第一次添加元素,条件成立
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        // 取最大值,DEFAULT_CAPACITY 的值为 10,minCapacity 第一次添加元素传入 1
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }

    ensureExplicitCapacity(minCapacity);
}

ensureExplicitCapacity method

private void ensureExplicitCapacity(int minCapacity) {
   modCount++;

   // 当容量不够时,进行扩容
   if (minCapacity - elementData.length > 0)
       grow(minCapacity);
}

grow method

private void grow(int minCapacity) {
    // 当前数组长度
    int oldCapacity = elementData.length;
    // 新的数组长度 = 当前数组长度 + (当前数组长度右移 1 位),第一次添加 newCapacity = 0
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    // 第一次添加元素,条件成立 0 - 10 < 0,赋值 newCapacity = 10,因此,调用无参构造方法默认数组大小为 10
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // 调用 copyOf 方法,创建新的大小为 newCapacity 的数组,并将原来数组的元素拷贝到新数组
    elementData = Arrays.copyOf(elementData, newCapacity);
}

2 delete elements

// 移除指定索引的元素
nums.remove(1);

remove method

public E remove(int index) {
    // 检测指定的索引是否越界
    rangeCheck(index);

    modCount++;
    // 获取待移除的元素,操作完成后返回
    E oldValue = elementData(index);

    // 计算出 index 之后元素的个数
    int numMoved = size - index - 1;
    if (numMoved > 0)
        // 调用 arraycopy 方法将 index 之后的元素向前移动一位,将 index 位置的元素覆盖掉
        System.arraycopy(elementData, index+1, elementData, index,
                         numMoved);
    // 将数组最后位置的值置为 null
    elementData[--size] = null; // clear to let GC do its work

    return oldValue;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325529217&siteId=291194637