zl程序教程

您现在的位置是:首页 >  后端

当前栏目

【Java】ArrayList源码

JAVA源码 ArrayList
2023-06-13 09:14:00 时间

The time you spend on your roses makes your roses so important.

ArrayList 源码分析

package Note.cistern;

import java.util.ArrayList;

public class ArrayListDemo {
    public static void main(String[] args) {
        ArrayList<Object> arrayList = new ArrayList<>();
        arrayList.add("e");
    }
}

属性和构造方法:

 private static final long serialVersionUID = 8683452581122892189L;

    /**
     * 默认的初始容量
     */
    private static final int DEFAULT_CAPACITY = 10;

    /**
     * 初始化一个空实例时的数组
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};

    /**
     *缺省空对象数组
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    /**
     * 保存数据的数组变量
     */
    transient Object[] elementData;

    /**
     * arrayList中实际的元素个数
     */
    private int size;
public ArrayList() {
    // 使用默认构造函数实例化ArrayList时,先初始化一个空数组
    // 相当于 this.elementData = 
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

add(E e)方法

public boolean add(E e) {
    // 该方法用来确保数组够用
    // 因为要保证剩余空间够放下一个新元素,所以要对size + 1判断
    ensureCapacityInternal(size + 1);
    // 把新元素放入数组,实际大小加一
    elementData[size++] = e;
    return true;
}
private void ensureCapacityInternal(int minCapacity) {
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
    // 如果数组elementData是空的(第一次添加数据)时
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        // 返回DEFAULT_CAPACITY(默认10)和minCapacity(调用)的最大值
        return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    // 否则直接返回minCapacity
    return minCapacity;
}
private void ensureExplicitCapacity(int minCapacity) {
    modCount++;

    // 对于第一次来说,minCapacity=10, elementData.length = 0
    // 这时elementData还是一个空数组,需要扩容才能放下新数据
    if (minCapacity - elementData.length > 0)
        // 扩容
        grow(minCapacity);
}
private void grow(int minCapacity) {
    // 旧的容量
    int oldCapacity = elementData.length;
    // 新容量是旧的的基础上扩容50%
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    // 针对第一次扩容的情况,这时oldCapacity=0, newCapacity=0
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    // 如果扩容后超过了最大容量限制
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        // 分配最大容量
        newCapacity = hugeCapacity(minCapacity);
    // 新容量确定,copy一个新容量的数组给ArrayList
    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;
}

其他add方法实现也大同小异,

public void add(int index, E element) {
    // 检查index是不是在规定范围内
    rangeCheckForAdd(index);
    // 确保容量够用
    ensureCapacityInternal(size + 1); 
    // 插入新元素
    System.arraycopy(elementData, index, elementData, index + 1,
                     size - index);
    elementData[index] = element;
    size++;
}
public boolean addAll(Collection<? extends E> c) {
    // Collection对象转换为数组
    Object[] a = c.toArray();
    int numNew = a.length;
    ensureCapacityInternal(size + numNew);  // Increments modCount
    // 合并两个数组
    System.arraycopy(a, 0, elementData, size, numNew);
    size += numNew;
    return numNew != 0;
}
public boolean addAll(int index, Collection<? extends E> c) {
    rangeCheckForAdd(index);

    Object[] a = c.toArray();
    int numNew = a.length;
    ensureCapacityInternal(size + numNew);  // Increments modCount

    int numMoved = size - index;
    if (numMoved > 0)
        // 原来的数据后移numNew位
        System.arraycopy(elementData, index, elementData, index + numNew,
                         numMoved);
    // 把新数据插入
    System.arraycopy(a, 0, elementData, index, numNew);
    size += numNew;
    return numNew != 0;
}