ArrayList源码解析

198 阅读4分钟

结构图

mark

  1. Iterable为ArraysList提供迭代器的功能
  2. Collection定义了集合的基础addgetremote...等功能
  3. AbstractCollectionCollection定义的接口进行了默认实现
  4. List定义列表相关接口
  5. AbstractListList定义的接口进行了默认实现
  6. RandomAccess为其增加快速随机访问的能力
  7. Cloneable为其增加克隆的能力
  8. Serializable为其增加序列化

关键属性及常用方法

关键属性

// 默认容量
private static final int DEFAULT_CAPACITY = 10;
// 空的元素数据
private static final Object[] EMPTY_ELEMENTDATA = {};
// 元素数据,存储目标元素
transient Object[] elementData;
// 元素大小 >= elementData.length;
private int size;

常用方法

构造器

ArraysList提供三个构造器,分别为

  1. 无参构造器
public ArrayList() {
    // 初始化原数据
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
  1. 通过初始容量进行初始化
if (initialCapacity > 0) {
    this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
    this.elementData = EMPTY_ELEMENTDATA;
} else {
    throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
}
  1. 通过集合进行初始化
public ArrayList(Collection<? extends E> c) {
    elementData = c.toArray();
    if ((size = elementData.length) != 0) {
        // 当c.toArray() 返回的不为 Object[]时,将原数据通过Arrays.copyOf()方法转化为Object[]
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    } else {
        // replace with empty array.
        this.elementData = EMPTY_ELEMENTDATA;
    }
}
基础方法
  1. 增加元素:add()
public boolean add(E e) {
    // 原数据扩容
    ensureCapacityInternal(size + 1);
    // 新元素赋值
    elementData[size++] = e;
    return true;
}

// 内部扩容
private void ensureCapacityInternal(int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    // 扩容
    ensureExplicitCapacity(minCapacity);
}

private void ensureExplicitCapacity(int minCapacity) {
    modCount++;
    
    // 新容量>当前数据容量,进行扩容
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

// 扩容
private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    // 新容量 = 老容量 * 1.5
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    // 新容量小于最小容量,则新容量=最小容量
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    // 当新容量已经超过最大的数组大小
    // 其中 MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        // 通过最小容量重新获取新容量
        newCapacity = hugeCapacity(minCapacity);
    // 原数据赋值
    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;
}
  1. 批量添加元素:
// 添加到元素数据的末尾
public boolean addAll(Collection<? extends E> c) {
    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)
        // 将 index -> size -1 的元素拷贝到元素数据的末尾
        System.arraycopy(elementData, index, elementData, index + numNew,
                         numMoved);
    // 将目标元素拷贝到指定位置
    System.arraycopy(a, 0, elementData, index, numNew);
    size += numNew;
    return numNew != 0;
}
  1. 获取元素:get()
public E get(int index) {
    // 范围检查
    rangeCheck(index);
    // 返回元素
    return elementData(index);
}
  1. 设置元素到指定位置:set()
public E set(int index, E element) {
    rangeCheck(index);
    
    E oldValue = elementData(index);
    elementData[index] = element;
    return oldValue;
}
  1. 移除指定元素:remove()
// 删除指定位置的元素
public E remove(int index) {
    rangeCheck(index);

    modCount++;
    E oldValue = elementData(index);

    int numMoved = size - index - 1;
    // 当删除的元素不是最后一个时
    if (numMoved > 0)
        // 将index后的元素向前拷贝
        System.arraycopy(elementData, index+1, elementData, index,
                         numMoved);
    elementData[--size] = null; // clear to let GC do its work

    return oldValue;
}
// 删除指定元素
// 只会删除满足条件的第一个元素
public boolean remove(Object o) {
    if (o == null) {
        for (int index = 0; index < size; index++)
            if (elementData[index] == null) {
                // 快速删除
                fastRemove(index);
                return true;
            }
    } else {
        for (int index = 0; index < size; index++)
            if (o.equals(elementData[index])) {
                // 快速删除
                fastRemove(index);
                return true;
            }
    }
    return false;
}
// 快速删除方法,与 remote(int index)方法实现一致
private void fastRemove(int index) {
    modCount++;
    int numMoved = size - index - 1;
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index,
                         numMoved);
    elementData[--size] = null; // clear to let GC do its work
}
  1. 清空元素:clear()
public void clear() {
    modCount++;

    // clear to let GC do its work
    // 将元素数据数组的所有item赋值为null
    for (int i = 0; i < size; i++)
        elementData[i] = null;

    size = 0;
}
  1. 批量删除元素:batchRemove()
private boolean batchRemove(Collection<?> c, boolean complement) {
    final Object[] elementData = this.elementData;
    int r = 0, w = 0;
    boolean modified = false;
    try {
        for (; r < size; r++)
            if (c.contains(elementData[r]) == complement)
                // 将不满足删除条件的元素向前移动
                elementData[w++] = elementData[r];
    } finally {
        // Preserve behavioral compatibility with AbstractCollection,
        // even if c.contains() throws.
        // 当抛出了异常时,可能会出现 r != size 的情况
        // 此时直接将未匹配的数据直接拷贝到最后一个移动后的数据后面
        if (r != size) {
            System.arraycopy(elementData, r,
                             elementData, w,
                             size - r);
            w += size - r;
        }
        // 当存在删除的数据时,将不满足条件后的索引位赋值为null
        if (w != size) {
            // clear to let GC do its work
            for (int i = w; i < size; i++)
                elementData[i] = null;
            modCount += size - w;
            size = w;
            modified = true;
        }
    }
    return modified;
}

上面从增删改查四个角度解析了ArrayList的基本源码,可以得出它的内部实现是一个数组。在新增元素时,当添加后的元素大小超过了元素数组的长度时,会触发它的扩容机制,以添加后的元素大小的1.5倍对元素数组进行扩容。