逐行读java源码-ArrayList

3 阅读29分钟

Java源码从集合中最常用的ArrayList读起。

1. 类定义与继承关系

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

关键接口与父类:

  • AbstractList :提供了 List 接口的骨架实现
  • List :定义了列表的基本操作
  • RandomAccess :标记接口,表示支持随机访问(常数时间复杂度)
  • Cloneable :支持克隆
  • Serializable :支持序列化

2. 核心成员变量

// 存储元素的底层数组
transient Object[] elementData;

// 实际元素数量
private int size;

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

// 空数组(用于默认构造函数)
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

// 空数组(用于指定初始容量为 0 的构造函数)
private static final Object[] EMPTY_ELEMENTDATA = {};
变量说明:
  • elementData :存储实际元素的数组,使用 transient 修饰以优化序列化
  • size :当前列表中的元素数量
  • DEFAULT_CAPACITY默认初始容量10
  • DEFAULTCAPACITY_EMPTY_ELEMENTDATA :默认构造函数使用的空数组
  • EMPTY_ELEMENTDATA :指定初始容量为 0 时使用的空数组
ArrayList 中的两个空数组 虽然内容相同,但语义不同:
  • DEFAULTCAPACITY_EMPTY_ELEMENTDATA :无参构造使用,首次扩容到 10
  • EMPTY_ELEMENTDATA :容量为 0 的构造使用,首次扩容到 1

这种设计体现了 Java 集合框架的 细致考虑 ,通过微小的差异提供了更符合用户预期的行为。

修饰符transient
  • transient 是 Java 中的 关键字 ,用于修饰类的成员变量
  • 作用 :标记该变量在 序列化 过程中会被 跳过 ,不参与序列化
  • 使用场景 :
    • 临时变量或缓存数据
    • 计算得出的值
    • 不需要持久化的字段
    • 敏感信息(如密码)
  • 常见的修饰符及作用:
    • static 静态成员,属于类而非实例 【变量、方法、代码块】
    • final 不可修改 【变量、方法、类】
    • private 私有访问,仅本类可见 【变量、方法】
    • protected 受保护访问,本包和子类可见 【变量、方法】
    • public 公共访问,任何地方可见 【类、变量、方法】
    • volatile 保证可见性和禁止重排序 【变量】
    • synchronized 同步锁 【方法、代码块】
    • native 本地方法,由其他语言实现 【方法】
    • abstract 抽象的,需要子类实现 【类、方法】

3. 构造函数

3.1 无参构造函数

public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
  • 初始化时使用 DEFAULTCAPACITY_EMPTY_ELEMENTDATA
  • 首次添加元素时会扩容到 DEFAULT_CAPACITY (10)

3.2 指定初始容量构造函数

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);
    }
}
  • 根据指定容量创建数组
  • 容量为 0 时使用 EMPTY_ELEMENTDATA

3.3 从其他集合构造

public ArrayList(Collection<? extends E> c) {
    elementData = c.toArray();
    if ((size = elementData.length) != 0) {
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    } else {
        this.elementData = EMPTY_ELEMENTDATA;
    }
}
  • 将集合转换为数组并赋值给 elementData
  • 处理类型不匹配的情况

4. 核心方法

4.1 添加元素

add(E e)

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // 确保容量足够
    elementData[size++] = e;  // 添加元素并递增 size
    return true;
}
  • 调用 ensureCapacityInternal 确保容量
  • 直接在 elementData[size] 位置添加元素
  • 时间复杂度: amortized O(1)(大部分情况下)(amortized均摊)

add(int index, E element)

public void add(int index, E element) {
    rangeCheckForAdd(index);  // 检查索引是否合法
    ensureCapacityInternal(size + 1);  // 确保容量足够
    System.arraycopy(elementData, index, elementData, index + 1, size - index);  // 移动
    元素
    elementData[index] = element;  // 插入元素
    size++;  // 递增 size
}
  • 检查索引范围
  • 移动指定位置后的元素
  • 插入新元素
  • 时间复杂度:O(n)(需要移动元素)

4.2 获取元素

public E get(int index) {
    rangeCheck(index);  // 检查索引是否合法
    return elementData(index);  // 返回对应位置的元素
}
E elementData(int index) {
    return (E) elementData[index];  // 类型转换
}
  • 检查索引范围
  • 直接通过数组索引访问
  • 时间复杂度:O(1)

4.3 删除元素

remove(int index)

public E remove(int index) {
    rangeCheck(index);  // 检查索引是否合法
    modCount++;  // 用于记录结构修改次数
    E oldValue = elementData(index);  // 获取旧值
    int numMoved = size - index - 1;  // 计算需要移动的元素数量
    if (numMoved > 0)
        System.arraycopy(elementData, index + 1, elementData, index, numMoved);  // 移动元素
    elementData[--size] = null;  // 清空最后一个位置,帮助 GC
    return oldValue;  // 返回被删除的元素
}
  • 检查索引范围
  • 判断是否需要移动元素:如果是最后一位即【index = size-1】则不需要移动,不是最后一位即【index<size-1】变形即【size - index - 1> 0】
  • 移动元素覆盖被删除的位置
  • 清空最后一个位置
  • 时间复杂度:O(n)(需要移动元素)
  • modCount变量来自AbstractList,用于记录结构修改次数,每次添加、删除元素时都会递增,用于快速失败机制、检测并发修改

4.4 扩容机制

ensureCapacityInternal(int minCapacity)

private void ensureCapacityInternal(int minCapacity) {
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {//由默认无参构造,首次扩容到10
        return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    return minCapacity;
}
private void ensureExplicitCapacity(int minCapacity) {
    modCount++;  // 修改计数
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);  // 调用 grow 方法扩容
}
  • 计算所需最小容量(无参数构造的默认空数组,首次扩容到10;构造时传入size0创建的空数组,首次扩容到1)
  • 检查是否需要扩容
  • 调用 grow 方法

grow(int minCapacity)

private Object[] grow(int minCapacity) {
    int oldCapacity = elementData.length;
    if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        int newCapacity = ArraysSupport.newLength(oldCapacity,
                minCapacity - oldCapacity,  // 最小增长
                oldCapacity >> 1);  // 首选增长(50%)
        return elementData = Arrays.copyOf(elementData, newCapacity);
    } else {
        return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
    }
}
  • 计算新容量(通常为旧容量的 1.5 倍)
  • 创建新数组并复制原元素
  • 更新 elementData 引用
  • 时间复杂度:O(n)(需要复制数组)

5. 迭代器实现

Java
private class Itr implements Iterator<E> {
    int cursor;       // 下一个要返回的元素索引
    int lastRet = -1// 上一个返回的元素索引
    int expectedModCount = modCount;  // 期望的修改计数
    public boolean hasNext() {
        return cursor != size;
    }
    @SuppressWarnings("unchecked")
    public E next() {
        checkForComodification();  // 检查并发修改
        int i = cursor;
        if (i >= size)
            throw new NoSuchElementException();
        Object[] elementData = ArrayList.this.elementData;
        if (i >= elementData.length)
            throw new ConcurrentModificationException();
        cursor = i + 1;
        return (E) elementData[lastRet = i];
    }
    public void remove() {
        if (lastRet < 0)
            throw new IllegalStateException();
        checkForComodification();  // 检查并发修改
        try {
            ArrayList.this.remove(lastRet);
            cursor = lastRet;
            lastRet = -1;
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }
    final void checkForComodification() {
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    }
}
  • 内部类实现 Iterator 接口
  • 支持 hasNext()、next()、remove() 方法
  • 检测并发修改(快速失败机制)

6. 其他重要方法

6.1 size()

Java
public int size() {
    return size;
}
  • 返回当前元素数量
  • 时间复杂度:O(1)

6.2 isEmpty()

Java
public boolean isEmpty() {
    return size == 0;
}
  • 检查是否为空
  • 时间复杂度:O(1)

6.3 clear()

Java
public void clear() {
    modCount++;
    // 清空所有元素引用,帮助 GC
    for (int i = 0; i < size; i++)
        elementData[i] = null;
    size = 0;
}
  • 清空所有元素
  • 时间复杂度:O(n)

6.4 contains(Object o)

Java
public boolean contains(Object o) {
    return indexOf(o) >= 0;
}
  • 检查是否包含指定元素
  • 调用 indexOf 方法

6.5 indexOf(Object o)

Java
public int indexOf(Object o) {
    if (o == null) {
        for (int i = 0; i < size; i++)
            if (elementData[i]==null)
                return i;
    } else {
        for (int i = 0; i < size; i++)
            if (o.equals(elementData[i]))
                return i;
    }
    return -1;
}
  • 查找元素的首次出现位置
  • 时间复杂度:O(n)

7. 线程安全性

  • ArrayList 是线程不安全的:多线程环境下可能导致并发修改异常或数据不一致

  • 解决方案

    • 使用 Collections.synchronizedList(new ArrayList<>())
    • 使用 CopyOnWriteArrayList
    • 手动同步(如使用 synchronized 块)

8. 性能特点

操作时间复杂度说明
随机访问(get/set)O(1)直接通过数组索引
添加元素(末尾)amortized O(1)大部分情况下直接添加,偶尔扩容
添加元素(中间)O(n)需要移动元素
删除元素O(n)需要移动元素
查找元素O(n)线性搜索

9. 与 LinkedList 的对比

特性ArrayListLinkedList
底层结构数组双向链表
随机访问O(1)O(n)
插入/删除(中间)O(n)O(1)
内存占用较紧凑每个节点额外存储前后引用
遍历效率高(连续内存)低(分散内存)
适用场景频繁随机访问、少量插入删除频繁插入删除、较少随机访问

10. 代码优化建议

  1. 预分配容量

    • 如果知道大致元素数量,使用 new ArrayList<>(initialCapacity) 减少扩容次数
  2. 避免频繁扩容

    • 对于大量元素,合理设置初始容量
  3. 使用 for-each 循环

    • 遍历元素时,for-each 比普通 for 循环更简洁
  4. 注意并发安全

    • 多线程环境下使用同步包装或并发集合
  5. 及时清理

    • 不再使用的 ArrayList 可以调用 clear() 帮助 GC

总结

ArrayList 是基于动态数组实现的 List 接口,通过以下核心机制提供高效的元素管理:

  • 动态扩容:自动调整容量以适应元素数量变化
  • 随机访问:常数时间复杂度的元素访问
  • 灵活操作:支持添加、删除、查找等基本操作
  • 快速失败:通过 modCount 检测并发修改

它是 Java 中最常用的集合类之一,适用于需要频繁随机访问元素的场景。

ArrayList源码

最后附上完整的ArrayList源码,其中包含了 ArrayList 类的全部实现代码,代码功能与原始 ArrayList 完全一致,并将所有英文注释都已翻译成中文。区别是直接包含了 ArraysSupport 辅助类的实现。

/**
 * ArrayList 是一个可调整大小的数组实现的 List 接口。
 * 实现了所有可选的 List 操作,并允许所有元素,包括 null。
 * 
 * <p>ArrayList 大致等同于 Vector,除了它是不同步的。
 * 
 * <p>ArrayList 的 size、isEmpty、get、set、iterator 和 listIterator 操作的时间复杂度是常数时间。
 * add 操作的时间复杂度是均摊常数时间,即添加 n 个元素需要 O(n) 时间。
 * 其他操作的时间复杂度是线性的。
 * 
 * <p>每个 ArrayList 实例都有一个容量。容量是用于存储列表元素的数组的大小。
 * 它总是至少与列表大小一样大。当元素被添加到 ArrayList 时,其容量会自动增长。
 * 增长策略的细节并未指定,因为它可能因实现而异。
 * 
 * <p>注意,此实现不是同步的。如果多个线程同时访问一个 ArrayList 实例,
 * 并且至少有一个线程修改了列表结构,那么它必须在外部进行同步。
 * (结构修改是指添加或删除一个或多个元素,或者显式调整底层数组的大小;
 * 仅仅设置元素的值不是结构修改。)这通常通过在自然封装列表的对象上进行同步来实现。
 * 如果不存在这样的对象,则应该使用 Collections.synchronizedList 方法
 * 来“包装”列表。最好在创建时完成此操作,以防止意外的不同步访问:
 * <pre>
 *   List list = Collections.synchronizedList(new ArrayList(...));
 * </pre>
 * 
 * <p>此类的 iterator 和 listIterator 方法返回的迭代器是快速失败的:
 * 如果在迭代器创建后的任何时间对列表进行结构修改,
 * 除了通过迭代器自己的 remove 或 add 方法外,迭代器将抛出 ConcurrentModificationException。
 * 因此,面对并发修改,迭代器快速而干净地失败,而不是在未来的不确定时间冒着任意、
 * 非确定性行为的风险。
 * 
 * <p>请注意,迭代器的快速失败行为不能保证,
 * 因为一般来说,在存在非同步并发修改的情况下,
 * 不可能做出任何硬性保证。快速失败迭代器尽最大努力抛出 ConcurrentModificationException。
 * 因此,编写依赖于此异常的程序是错误的:
 * 迭代器的快速失败行为应该仅用于检测错误。
 * 
 * <p>此实现是 Java 集合框架的成员。
 *
 * @param <E> 此列表中元素的类型
 * @author Josh Bloch
 * @author Neal Gafter
 * @see Collection
 * @see List
 * @see LinkedList
 * @see Vector
 * @since 1.2
 */
import java.util.*;
import java.util.function.*;
import java.util.stream.*;
import java.io.*;

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
    private static final long serialVersionUID = 8683452581122892189L;

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

    /**
     * 用于默认构造函数的空数组。
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    /**
     * 存储 ArrayList 元素的数组缓冲区。
     * ArrayList 的容量是此数组缓冲区的长度。
     * 当添加第一个元素时,任何带有 elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA 的空 ArrayList
     * 都将被扩展为 DEFAULT_CAPACITY。
     */
    transient Object[] elementData; // 非私有以简化嵌套类访问

    /**
     * ArrayList 中的元素数量。
     */
    private int size;

    /**
     * 构造一个初始容量为 10 的空列表。
     */
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    /**
     * 构造一个具有指定初始容量的空列表。
     *
     * @param  initialCapacity  列表的初始容量
     * @throws IllegalArgumentException 如果指定的初始容量为负
     */
    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);
        }
    }

    /**
     * 构造一个包含指定集合元素的列表,元素的顺序由集合的迭代器返回。
     *
     * @param c 其元素将被放入此列表的集合
     * @throws NullPointerException 如果指定的集合为 null
     */
    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // c.toArray 可能(不正确地)不返回 Object[](见 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // 用空数组替换
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

    /**
     * 用于空实例的共享空数组实例。
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};

    /**
     *  trimToSize 方法将容量调整为列表的当前大小。
     */
    public void trimToSize() {
        modCount++;
        if (size < elementData.length) {
            elementData = (size == 0)
              ? EMPTY_ELEMENTDATA
              : Arrays.copyOf(elementData, size);
        }
    }

    /**
     * 确保此列表的容量至少为指定的最小容量。
     *
     * @param   minCapacity   所需的最小容量
     */
    public void ensureCapacity(int minCapacity) {
        int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
            ? 0
            : DEFAULT_CAPACITY;

        if (minCapacity > minExpand) {
            ensureExplicitCapacity(minCapacity);
        }
    }

    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++;

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

    /**
     * 要分配的最大数组大小。
     * 一些 VMs 在数组中保留一些头字。
     * 尝试分配更大的数组可能会导致 OutOfMemoryError:请求的数组大小超过 VM 限制
     */
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    /**
     * 增加容量以确保它至少能容纳最小容量参数指定的元素数量。
     *
     * @param minCapacity 所需的最小容量
     * @return 增长后的元素数组
     */
    private Object[] grow(int minCapacity) {
        int oldCapacity = elementData.length;
        if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            int newCapacity = ArraysSupport.newLength(oldCapacity,
                    minCapacity - oldCapacity, /* minimum growth */
                    oldCapacity >> 1           /* preferred growth */);
            return elementData = Arrays.copyOf(elementData, newCapacity);
        } else {
            return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
        }
    }

    private Object[] grow() {
        return grow(size + 1);
    }

    /**
     * 返回此列表中的元素数。
     *
     * @return 此列表中的元素数
     */
    public int size() {
        return size;
    }

    /**
     * 如果此列表不包含元素,则返回 true。
     *
     * @return 如果此列表不包含元素,则为 true
     */
    public boolean isEmpty() {
        return size == 0;
    }

    /**
     * 如果此列表包含指定的元素,则返回 true。
     * 更正式地说,当且仅当此列表包含至少一个元素 e 使得
     * (o==null ? e==null : o.equals(e)) 时,返回 true。
     *
     * @param o 要测试其在此列表中是否存在的元素
     * @return 如果此列表包含指定的元素,则为 true
     */
    public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }

    /**
     * 返回此列表中指定元素的首次出现的索引,
     * 如果此列表不包含该元素,则返回 -1。
     * 更正式地说,返回最小的索引 i 使得
     * (o==null ? get(i)==null : o.equals(get(i))),
     * 如果没有这样的索引,则返回 -1。
     *
     * @param o 要搜索的元素
     * @return 此列表中指定元素的首次出现的索引,
     *         如果此列表不包含该元素,则返回 -1
     */
    public int indexOf(Object o) {
        return indexOfRange(o, 0, size);
    }

    int indexOfRange(Object o, int start, int end) {
        Object[] es = elementData;
        if (o == null) {
            for (int i = start; i < end; i++) {
                if (es[i] == null) {
                    return i;
                }
            }
        } else {
            for (int i = start; i < end; i++) {
                if (o.equals(es[i])) {
                    return i;
                }
            }
        }
        return -1;
    }

    /**
     * 返回此列表中指定元素的最后一次出现的索引,
     * 如果此列表不包含该元素,则返回 -1。
     * 更正式地说,返回最大的索引 i 使得
     * (o==null ? get(i)==null : o.equals(get(i))),
     * 如果没有这样的索引,则返回 -1。
     *
     * @param o 要搜索的元素
     * @return 此列表中指定元素的最后一次出现的索引,
     *         如果此列表不包含该元素,则返回 -1
     */
    public int lastIndexOf(Object o) {
        return lastIndexOfRange(o, 0, size);
    }

    int lastIndexOfRange(Object o, int start, int end) {
        Object[] es = elementData;
        if (o == null) {
            for (int i = end - 1; i >= start; i--) {
                if (es[i] == null) {
                    return i;
                }
            }
        } else {
            for (int i = end - 1; i >= start; i--) {
                if (o.equals(es[i])) {
                    return i;
                }
            }
        }
        return -1;
    }

    /**
     * 返回此 ArrayList 实例的浅拷贝。
     * (元素本身不会被复制。)
     *
     * @return 此 ArrayList 实例的浅拷贝
     */
    public Object clone() {
        try {
            ArrayList<?> v = (ArrayList<?>) super.clone();
            v.elementData = Arrays.copyOf(elementData, size);
            v.modCount = 0;
            return v;
        } catch (CloneNotSupportedException e) {
            // 这不可能发生,因为我们是 Cloneable
            throw new InternalError(e);
        }
    }

    /**
     * 返回一个包含此列表中所有元素的数组,
     * 按照它们在此列表中的顺序排列。
     *
     * <p>返回的数组将是“安全的”,因为此列表不维护对它的引用。
     * (换句话说,此方法必须分配一个新数组)。
     * 因此,调用者可以自由修改返回的数组。
     *
     * <p>此方法充当基于数组的 API 和基于集合的 API 之间的桥梁。
     *
     * @return 一个包含此列表中所有元素的数组,
     *         按照它们在此列表中的顺序排列
     */
    public Object[] toArray() {
        return Arrays.copyOf(elementData, size);
    }

    /**
     * 返回一个包含此列表中所有元素的数组,
     * 按照它们在此列表中的顺序排列;
     * 返回的数组的运行时类型是指定数组的运行时类型。
     * 如果列表适合指定的数组,则返回其中。
     * 否则,将分配一个新的数组,其运行时类型是指定数组的运行时类型,
     * 长度是此列表的大小。
     *
     * <p>如果列表适合指定的数组,并且有剩余空间(即数组的元素多于列表),
     * 则数组中紧接列表末尾的元素将被设置为 null。
     * (这仅在调用者知道列表不包含任何 null 元素时才有用。)
     *
     * @param a 要存储列表元素的数组,如果它足够大;否则,
     *          一个具有相同运行时类型的新数组将被分配用于此目的。
     * @return 一个包含此列表中所有元素的数组,
     *         按照它们在此列表中的顺序排列
     * @throws ArrayStoreException 如果指定数组的运行时类型不是此列表中每个元素的运行时类型的超类型
     * @throws NullPointerException 如果指定的数组为 null
     */
    @SuppressWarnings("unchecked")
    public <T> T[] toArray(T[] a) {
        if (a.length < size) {
            // 制作一个与指定数组相同运行时类型的新数组
            return (T[]) Arrays.copyOf(elementData, size, a.getClass());
        }
        System.arraycopy(elementData, 0, a, 0, size);
        if (a.length > size) {
            a[size] = null;
        }
        return a;
    }

    // Positional Access Operations

    @SuppressWarnings("unchecked")
    E elementData(int index) {
        return (E) elementData[index];
    }

    /**
     * 返回此列表中指定位置的元素。
     *
     * @param  index 要返回的元素的索引
     * @return 此列表中指定位置的元素
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public E get(int index) {
        Objects.checkIndex(index, size);
        return elementData(index);
    }

    /**
     * 用指定的元素替换此列表中指定位置的元素。
     *
     * @param index 要替换的元素的索引
     * @param element 要存储在指定位置的元素
     * @return 被替换的元素
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public E set(int index, E element) {
        Objects.checkIndex(index, size);
        E oldValue = elementData(index);
        elementData[index] = element;
        return oldValue;
    }

    /**
     * 将指定的元素追加到此列表的末尾。
     *
     * @param e 要追加到此列表的元素
     * @return {@code true}(根据 {@link Collection#add} 的约定)
     */
    public boolean add(E e) {
        modCount++;
        add(e, elementData, size);
        return true;
    }

    private void add(E e, Object[] elementData, int s) {
        if (s == elementData.length)
            elementData = grow();
        elementData[s] = e;
        size = s + 1;
    }

    /**
     * 在此列表中的指定位置插入指定的元素。
     * 将当前在该位置的元素(如果有)和任何后续元素向右移动(将其索引加一)。
     *
     * @param index 要插入指定元素的索引
     * @param element 要插入的元素
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public void add(int index, E element) {
        rangeCheckForAdd(index);
        modCount++;
        final int s;
        Object[] elementData;
        if ((s = size) == (elementData = this.elementData).length)
            elementData = grow();
        System.arraycopy(elementData, index, elementData, index + 1, s - index);
        elementData[index] = element;
        size = s + 1;
    }

    /**
     * 移除此列表中指定位置的元素。
     * 将任何后续元素向左移动(从其索引中减去一)。
     *
     * @param index 要移除的元素的索引
     * @return 被移除的元素
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public E remove(int index) {
        Objects.checkIndex(index, size);
        final Object[] es = elementData;

        @SuppressWarnings("unchecked") E oldValue = (E) es[index];
        fastRemove(es, index);

        return oldValue;
    }

    /**
     * 移除此列表中首次出现的指定元素(如果存在)。
     * 如果列表不包含该元素,则它不会被更改。
     * 更正式地说,移除具有最低索引 i 的元素,使得
     * (o==null ? get(i)==null : o.equals(get(i)))(如果存在这样的元素)。
     *
     * @param o 要从列表中移除的元素(如果存在)
     * @return 如果列表包含指定的元素,则为 true
     */
    public boolean remove(Object o) {
        final Object[] es = elementData;
        final int size = this.size;
        int i = 0;
        found:
        {
            if (o == null) {
                for (; i < size; i++)
                    if (es[i] == null)
                        break found;
            } else {
                for (; i < size; i++)
                    if (o.equals(es[i]))
                        break found;
            }
            return false;
        }
        fastRemove(es, i);
        return true;
    }

    /**
     * 私有 remove 方法,跳过边界检查且不返回移除的值。
     */
    private void fastRemove(Object[] es, int i) {
        modCount++;
        final int newSize;
        if ((newSize = size - 1) > i)
            System.arraycopy(es, i + 1, es, i, newSize - i);
        es[size = newSize] = null; // 帮助 GC
    }

    /**
     * 移除此列表中的所有元素。
     * 此调用返回后,列表将为空。
     */
    public void clear() {
        modCount++;
        final Object[] es = elementData;
        for (int to = size, i = size = 0; i < to; i++)
            es[i] = null;
    }

    /**
     * 按指定集合的迭代器返回的顺序,将指定集合中的所有元素追加到此列表的末尾。
     * 如果在操作进行中修改了指定的集合,则此操作的行为是未定义的。
     * (这意味着如果指定的集合是此列表,并且此列表非空,则此调用的行为是未定义的。)
     *
     * @param c 要追加到此列表的元素的集合
     * @return {@code true} 如果此列表由于调用而更改
     * @throws NullPointerException 如果指定的集合为 null
     */
    public boolean addAll(Collection<? extends E> c) {
        Object[] a = c.toArray();
        modCount++;
        int numNew = a.length;
        if (numNew == 0)
            return false;
        Object[] elementData;
        final int s;
        if ((s = size) + numNew > (elementData = this.elementData).length)
            elementData = grow(s + numNew);
        System.arraycopy(a, 0, elementData, s, numNew);
        size = s + numNew;
        return true;
    }

    /**
     * 从指定的位置开始,将指定集合中的所有元素插入到此列表中。
     * 将当前在该位置的元素(如果有)和任何后续元素向右移动(增加其索引)。
     * 新元素将按照指定集合的迭代器返回的顺序出现在列表中。
     *
     * @param index 要插入指定集合中第一个元素的索引
     * @param c 要插入到此列表的元素的集合
     * @return {@code true} 如果此列表由于调用而更改
     * @throws IndexOutOfBoundsException {@inheritDoc}
     * @throws NullPointerException 如果指定的集合为 null
     */
    public boolean addAll(int index, Collection<? extends E> c) {
        rangeCheckForAdd(index);

        Object[] a = c.toArray();
        modCount++;
        int numNew = a.length;
        if (numNew == 0)
            return false;
        Object[] elementData;
        final int s;
        if ((s = size) + numNew > (elementData = this.elementData).length)
            elementData = grow(s + numNew);

        int numMoved = s - index;
        if (numMoved > 0)
            System.arraycopy(elementData, index, elementData, index + numNew, numMoved);

        System.arraycopy(a, 0, elementData, index, numNew);
        size = s + numNew;
        return true;
    }

    /**
     * 从此列表中移除所有索引在 fromIndex(包含)和 toIndex(不包含)之间的元素。
     * 将任何后续元素向左移动(减少其索引)。
     * 此调用缩短了列表的长度 by (toIndex - fromIndex)。
     * (如果 toIndex==fromIndex,则此操作无效。)
     *
     * @throws IndexOutOfBoundsException if fromIndex or toIndex is out of range
     *         ({@code fromIndex < 0 || toIndex > size || toIndex < fromIndex})
     */
    protected void removeRange(int fromIndex, int toIndex) {
        if (fromIndex > toIndex) {
            throw new IndexOutOfBoundsException(outOfBoundsMsg(fromIndex, toIndex));
        }
        modCount++;
        shiftTailOverGap(elementData, fromIndex, toIndex);
    }

    /**
     * 移除此列表中所有也包含在指定集合中的元素。
     *
     * @param c 包含要从此列表中移除的元素的集合
     * @return {@code true} 如果此列表由于调用而更改
     * @throws ClassCastException 如果此列表的元素的类型与指定集合不兼容
     *         (<a href="Collection.html#optional-restrictions">optional</a>)
     * @throws NullPointerException 如果此列表包含 null 元素且指定的集合不允许 null 元素
     *         (<a href="Collection.html#optional-restrictions">optional</a>),
     *         或者指定的集合为 null
     * @see Collection#contains(Object)
     */
    public boolean removeAll(Collection<?> c) {
        return batchRemove(c, false, 0, size);
    }

    /**
     * 仅保留此列表中也包含在指定集合中的元素。
     * 换句话说,移除此列表中所有不在指定集合中的元素。
     *
     * @param c 包含要保留在此列表中的元素的集合
     * @return {@code true} 如果此列表由于调用而更改
     * @throws ClassCastException 如果此列表的元素的类型与指定集合不兼容
     *         (<a href="Collection.html#optional-restrictions">optional</a>)
     * @throws NullPointerException 如果此列表包含 null 元素且指定的集合不允许 null 元素
     *         (<a href="Collection.html#optional-restrictions">optional</a>),
     *         或者指定的集合为 null
     * @see Collection#contains(Object)
     */
    public boolean retainAll(Collection<?> c) {
        return batchRemove(c, true, 0, size);
    }

    /**
     * 批处理删除或保留操作。
     * 
     * @param c 要删除或保留的元素的集合
     * @param complement 如果为 true,则保留元素;如果为 false,则删除元素
     * @param from 开始索引
     * @param end 结束索引
     * @return 如果列表被修改,则为 true
     */
    private boolean batchRemove(Collection<?> c, boolean complement, final int from, final int end) {
        Objects.requireNonNull(c);
        final Object[] es = elementData;
        int r = from, w = from;
        boolean modified = false;
        try {
            for (; r < end; r++)
                if (c.contains(es[r]) == complement)
                    es[w++] = es[r];
        } finally {
            // 即使 c.contains() 抛出异常,也保持一致性
            if (r != end) {
                System.arraycopy(es, r, es, w, end - r);
                w += end - r;
            }
            if (w != end) {
                // 清除从 w 到末尾的元素
                for (int i = w; i < end; i++)
                    es[i] = null;
                modCount += end - w;
                size = w;
                modified = true;
            }
        }
        return modified;
    }

    /**
     * 检查索引是否在范围内。
     */
    private void rangeCheckForAdd(int index) {
        if (index > size || index < 0) {
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
        }
    }

    /**
     * 构造一个 IndexOutOfBoundsException 细节消息。
     */
    private String outOfBoundsMsg(int index) {
        return "Index: " + index + ", Size: " + size;
    }

    private String outOfBoundsMsg(int fromIndex, int toIndex) {
        return "From Index: " + fromIndex + ", To Index: " + toIndex + ", Size: " + size;
    }

    /**
     * 从指定的位置开始,将所有元素向左移动,覆盖 gap。
     */
    private void shiftTailOverGap(Object[] es, int lo, int hi) {
        System.arraycopy(es, hi, es, lo, size - hi);
        int to = size;
        size -= hi - lo;
        for (int i = size; i < to; i++)
            es[i] = null;
    }

    /**
     * 返回此列表中元素的列表迭代器(按适当的顺序),从列表中的指定位置开始。
     * 指定的索引指示首次调用 next 时将返回的元素。
     * 首次调用 previous 将返回索引为 index-1 的元素。
     *
     * <p>列表迭代器是快速失败的:如果在创建迭代器后的任何时间对列表进行结构修改,
     * 除了通过列表迭代器自己的 remove 或 add 方法外,
     * 列表迭代器将抛出 ConcurrentModificationException。
     * 因此,面对并发修改,迭代器快速而干净地失败,
     * 而不是在未来的不确定时间冒着任意、非确定性行为的风险。
     *
     * @param index 要从其开始列表迭代的索引(通过 next() 的首次调用返回的元素)
     * @return 此列表中元素的列表迭代器(按适当的顺序),从列表中的指定位置开始
     * @throws IndexOutOfBoundsException 如果索引超出范围
     *         ({@code index < 0 || index > size()})
     */
    public ListIterator<E> listIterator(int index) {
        rangeCheckForAdd(index);
        return new ListItr(index);
    }

    /**
     * 返回此列表中元素的列表迭代器(按适当的顺序)。
     *
     * <p>列表迭代器是快速失败的:如果在创建迭代器后的任何时间对列表进行结构修改,
     * 除了通过列表迭代器自己的 remove 或 add 方法外,
     * 列表迭代器将抛出 ConcurrentModificationException。
     * 因此,面对并发修改,迭代器快速而干净地失败,
     * 而不是在未来的不确定时间冒着任意、非确定性行为的风险。
     *
     * @return 此列表中元素的列表迭代器(按适当的顺序)
     */
    public ListIterator<E> listIterator() {
        return new ListItr(0);
    }

    /**
     * 返回此列表中元素的迭代器(按适当的顺序)。
     *
     * <p>迭代器是快速失败的:如果在创建迭代器后的任何时间对列表进行结构修改,
     * 除了通过迭代器自己的 remove 方法外,
     * 迭代器将抛出 ConcurrentModificationException。
     * 因此,面对并发修改,迭代器快速而干净地失败,
     * 而不是在未来的不确定时间冒着任意、非确定性行为的风险。
     *
     * @return 此列表中元素的迭代器(按适当的顺序)
     */
    public Iterator<E> iterator() {
        return new Itr();
    }

    /**
     * 一个优化的迭代器实现,用于 ArrayList。
     */
    private class Itr implements Iterator<E> {
        int cursor;       // 下一个要返回的元素的索引
        int lastRet = -1; // 上一个返回的元素的索引;如果没有则为 -1
        int expectedModCount = modCount; // 期望的修改计数

        // 防止创建除了 ArrayList 之外的实例
        Itr() {}

        public boolean hasNext() {
            return cursor != size;
        }

        @SuppressWarnings("unchecked")
        public E next() {
            checkForComodification();
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            return (E) elementData[lastRet = i];
        }

        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                ArrayList.this.remove(lastRet);
                cursor = lastRet;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

        @Override
        public void forEachRemaining(Consumer<? super E> action) {
            Objects.requireNonNull(action);
            final int size = ArrayList.this.size;
            int i = cursor;
            if (i < size) {
                final Object[] es = elementData;
                if (i >= es.length) {
                    throw new ConcurrentModificationException();
                }
                for (; i < size && modCount == expectedModCount; i++) {
                    action.accept((E) es[i]);
                }
                // 更新迭代器状态
                cursor = i;
                lastRet = i - 1;
                checkForComodification();
            }
        }

        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }

    /**
     * 一个优化的 ListIterator 实现,用于 ArrayList。
     */
    private class ListItr extends Itr implements ListIterator<E> {
        ListItr(int index) {
            super();
            cursor = index;
        }

        public boolean hasPrevious() {
            return cursor != 0;
        }

        public int nextIndex() {
            return cursor;
        }

        public int previousIndex() {
            return cursor - 1;
        }

        @SuppressWarnings("unchecked")
        public E previous() {
            checkForComodification();
            int i = cursor - 1;
            if (i < 0)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i;
            return (E) elementData[lastRet = i];
        }

        public void set(E e) {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                ArrayList.this.set(lastRet, e);
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

        public void add(E e) {
            checkForComodification();

            try {
                int i = cursor;
                ArrayList.this.add(i, e);
                cursor = i + 1;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }
    }

    /**
     * 返回此列表的部分视图,从指定的 fromIndex(包含)到 toIndex(不包含)。
     * (如果 fromIndex 和 toIndex 相等,则返回的列表为空。)
     * 返回的列表由此列表支持,因此返回列表中的非结构性更改会反映在此列表中,
     * 反之亦然。返回的列表支持此列表支持的所有可选列表操作。
     *
     * <p>此方法消除了对显式范围操作(通常用于数组)的需要。
     * 任何期望列表的操作都可以通过传递 subList 视图而不是整个列表来用作范围操作。
     * 例如,以下语句从列表中移除了一系列元素:
     * <pre>
     *      list.subList(from, to).clear();
     * </pre>
     *
     * <p>返回的列表的迭代器是快速失败的:如果在创建迭代器后的任何时间对
     * 原始列表进行结构修改,除了通过返回列表的迭代器自己的 remove 或 add 方法外,
     * 迭代器将抛出 ConcurrentModificationException。
     * 因此,面对并发修改,迭代器快速而干净地失败,
     * 而不是在未来的不确定时间冒着任意、非确定性行为的风险。
     *
     * @param fromIndex 子列表的低端点(包含)
     * @param toIndex 子列表的高端点(不包含)
     * @return 此列表中指定范围的视图
     * @throws IndexOutOfBoundsException 如果 fromIndex 或 toIndex 超出范围
     *         ({@code fromIndex < 0 || toIndex > size || fromIndex > toIndex})
     */
    public List<E> subList(int fromIndex, int toIndex) {
        subListRangeCheck(fromIndex, toIndex, size);
        return new SubList(this, 0, fromIndex, toIndex);
    }

    static void subListRangeCheck(int fromIndex, int toIndex, int size) {
        if (fromIndex < 0) {
            throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
        }
        if (toIndex > size) {
            throw new IndexOutOfBoundsException("toIndex = " + toIndex);
        }
        if (fromIndex > toIndex) {
            throw new IllegalArgumentException("fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
        }
    }

    /**
     * 表示 ArrayList 的子列表的类。
     * 对 SubList 的操作会影响原始 ArrayList。
     */
    private class SubList extends AbstractList<E>
            implements RandomAccess
    {
        private final ArrayList<E> root;
        private final SubList parent;
        private final int offset;
        private int size;

        SubList(ArrayList<E> root, int offset, int fromIndex, int toIndex) {
            this.root = root;
            this.parent = null;
            this.offset = fromIndex;
            this.size = toIndex - fromIndex;
            this.modCount = root.modCount;
        }

        SubList(SubList parent, int offset, int fromIndex, int toIndex) {
            this.root = parent.root;
            this.parent = parent;
            this.offset = parent.offset + fromIndex;
            this.size = toIndex - fromIndex;
            this.modCount = root.modCount;
        }

        public E set(int index, E element) {
            rangeCheck(index);
            checkForComodification();
            E oldValue = root.elementData(offset + index);
            root.elementData[offset + index] = element;
            return oldValue;
        }

        public E get(int index) {
            rangeCheck(index);
            checkForComodification();
            return root.elementData(offset + index);
        }

        public int size() {
            checkForComodification();
            return size;
        }

        public void add(int index, E element) {
            rangeCheckForAdd(index);
            checkForComodification();
            root.add(offset + index, element);
            updateSizeAndModCount(1);
        }

        public E remove(int index) {
            rangeCheck(index);
            checkForComodification();
            E result = root.remove(offset + index);
            updateSizeAndModCount(-1);
            return result;
        }

        protected void removeRange(int fromIndex, int toIndex) {
            checkForComodification();
            root.removeRange(offset + fromIndex, offset + toIndex);
            updateSizeAndModCount(fromIndex - toIndex);
        }

        public boolean addAll(Collection<? extends E> c) {
            return addAll(size, c);
        }

        public boolean addAll(int index, Collection<? extends E> c) {
            rangeCheckForAdd(index);
            int cSize = c.size();
            if (cSize == 0)
                return false;

            checkForComodification();
            root.addAll(offset + index, c);
            updateSizeAndModCount(cSize);
            return true;
        }

        public Iterator<E> iterator() {
            return listIterator();
        }

        public ListIterator<E> listIterator(final int index) {
            checkForComodification();
            rangeCheckForAdd(index);

            final int offset = this.offset;

            return new ListIterator<E>() {
                int cursor = index;
                int lastRet = -1;
                int expectedModCount = modCount;

                public boolean hasNext() {
                    return cursor != SubList.this.size;
                }

                @SuppressWarnings("unchecked")
                public E next() {
                    checkForComodification();
                    int i = cursor;
                    if (i >= SubList.this.size)
                        throw new NoSuchElementException();
                    ArrayList<E> root = SubList.this.root;
                    int o = offset + i;
                    if (o >= root.size())
                        throw new ConcurrentModificationException();
                    cursor = i + 1;
                    return (E) root.elementData[lastRet = o];
                }

                public boolean hasPrevious() {
                    return cursor != 0;
                }

                @SuppressWarnings("unchecked")
                public E previous() {
                    checkForComodification();
                    int i = cursor - 1;
                    if (i < 0)
                        throw new NoSuchElementException();
                    ArrayList<E> root = SubList.this.root;
                    int o = offset + i;
                    cursor = i;
                    return (E) root.elementData[lastRet = o];
                }

                public int nextIndex() {
                    return cursor;
                }

                public int previousIndex() {
                    return cursor - 1;
                }

                public void remove() {
                    if (lastRet < 0)
                        throw new IllegalStateException();
                    checkForComodification();

                    try {
                        SubList.this.remove(lastRet - offset);
                        cursor = lastRet - offset;
                        lastRet = -1;
                        expectedModCount = modCount;
                    } catch (IndexOutOfBoundsException ex) {
                        throw new ConcurrentModificationException();
                    }
                }

                public void set(E e) {
                    if (lastRet < 0)
                        throw new IllegalStateException();
                    checkForComodification();

                    try {
                        root.set(lastRet, e);
                    } catch (IndexOutOfBoundsException ex) {
                        throw new ConcurrentModificationException();
                    }
                }

                public void add(E e) {
                    checkForComodification();

                    try {
                        int i = cursor;
                        SubList.this.add(i, e);
                        cursor = i + 1;
                        lastRet = -1;
                        expectedModCount = modCount;
                    } catch (IndexOutOfBoundsException ex) {
                        throw new ConcurrentModificationException();
                    }
                }

                final void checkForComodification() {
                    if (expectedModCount != SubList.this.modCount)
                        throw new ConcurrentModificationException();
                }
            };
        }

        public List<E> subList(int fromIndex, int toIndex) {
            subListRangeCheck(fromIndex, toIndex, size);
            return new SubList(this, offset, fromIndex, toIndex);
        }

        private void rangeCheck(int index) {
            if (index < 0 || index >= size) {
                throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
            }
        }

        private void rangeCheckForAdd(int index) {
            if (index < 0 || index > size) {
                throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
            }
        }

        private String outOfBoundsMsg(int index) {
            return "Index: " + index + ", Size: " + size;
        }

        private void checkForComodification() {
            if (root.modCount != modCount) {
                throw new ConcurrentModificationException();
            }
        }

        private void updateSizeAndModCount(int sizeChange) {
            modCount = root.modCount;
            size += sizeChange;
            if (parent != null) {
                parent.updateSizeAndModCount(sizeChange);
            }
        }
    }

    /**
     * 保存 ArrayList 实例的状态到一个流中(即序列化它)。
     *
     * @serialData 列表的大小(int),然后是所有元素(每个元素的类型为 E)
     */
    private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
        // 写入默认序列化
        s.defaultWriteObject();

        // 写入大小
        s.writeInt(size);

        // 写入所有元素
        for (int i=0; i<size; i++) {
            s.writeObject(elementData[i]);
        }
    }

    /**
     * 从一个流中恢复 ArrayList 实例的状态(即反序列化它)。
     */
    private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
        // 读取默认序列化
        s.defaultReadObject();

        // 读取大小
        int size = s.readInt();

        if (size > 0) {
            // 计算容量
            int capacity = calculateCapacity(EMPTY_ELEMENTDATA, size);
            SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Object[].class, capacity);
            Object[] elements = new Object[capacity];

            // 读取所有元素
            for (int i=0; i<size; i++) {
                elements[i] = s.readObject();
            }

            elementData = elements;
        } else if (size == 0) {
            elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new java.io.InvalidObjectException("Invalid size: " + size);
        }
    }

    /**
     * 创建一个包含此列表中所有元素的 Spliterator。
     *
     * <p>返回的 spliterator 是 <em>late-binding</em> 的。
     * <em>fail-fast</em> 的:在创建 spliterator 后的任何时间对列表进行结构修改,
     * 除了通过 spliterator 自己的 remove 方法外,
     * 将导致 spliterator 抛出 ConcurrentModificationException。
     *
     * @return 此列表中元素的 spliterator
     * @since 1.8
     */
    @Override
    public Spliterator<E> spliterator() {
        return new ArrayListSpliterator<>(this, 0, -1, 0);
    }

    /**
     * ArrayList 的 Spliterator 实现。
     */
    static final class ArrayListSpliterator<E> implements Spliterator<E> {
        /*
         * 如果 ArrayList 被修改,使用 expectedModCount 来检测,
         * 否则使用 cachedModCount。
         */
        private final ArrayList<E> list;
        private int index; // 当前位置,从 0 开始
        private int fence; // -1 表示需要计算
        private int expectedModCount; // 初始时为 0

        /** 创建覆盖给定列表的所有元素的 spliterator。 */
        ArrayListSpliterator(ArrayList<E> list, int origin, int fence, int expectedModCount) {
            this.list = list;
            this.index = origin;
            this.fence = fence;
            this.expectedModCount = expectedModCount;
        }

        private int getFence() { // 延迟初始化 fence
            int hi;
            ArrayList<E> lst;
            if ((hi = fence) < 0) {
                if ((lst = list) == null)
                    hi = fence = 0;
                else {
                    expectedModCount = lst.modCount;
                    hi = fence = lst.size;
                }
            }
            return hi;
        }

        public ArrayListSpliterator<E> trySplit() {
            int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
            return (lo >= mid) ? null : // 太小,无法拆分
                new ArrayListSpliterator<E>(list, lo, index = mid, expectedModCount);
        }

        public boolean tryAdvance(Consumer<? super E> action) {
            if (action == null) {
                throw new NullPointerException();
            }
            int hi = getFence(), i = index;
            if (i < hi) {
                index = i + 1;
                @SuppressWarnings("unchecked") E e = (E)list.elementData[i];
                action.accept(e);
                if (list.modCount != expectedModCount) {
                    throw new ConcurrentModificationException();
                }
                return true;
            }
            return false;
        }

        public void forEachRemaining(Consumer<? super E> action) {
            int i, hi, mc;
            ArrayList<E> lst;
            Object[] es;
            if (action == null) {
                throw new NullPointerException();
            }
            if ((lst = list) != null && (es = lst.elementData) != null) {
                if ((hi = fence) < 0) {
                    mc = lst.modCount;
                    hi = lst.size;
                } else {
                    mc = expectedModCount;
                }
                if ((i = index) >= 0 && (index = hi) <= es.length) {
                    for (; i < hi; ++i) {
                        @SuppressWarnings("unchecked") E e = (E) es[i];
                        action.accept(e);
                    }
                    if (lst.modCount == mc) {
                        return;
                    }
                }
            }
            throw new ConcurrentModificationException();
        }

        public long estimateSize() {
            return (long) (getFence() - index);
        }

        public int characteristics() {
            return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED |
                Spliterator.IMMUTABLE | Spliterator.CONCURRENT;
        }
    }

    /**
     * 按照指定的比较器对此列表进行排序。
     *
     * <p>此列表必须是可排序的,即列表中的所有元素必须通过指定的比较器进行相互比较。
     *
     * <p>此实现将列表转储到一个数组中,对数组进行排序,
     * 然后遍历列表,从数组中重新设置每个元素。
     * 这避免了在排序过程中发生的 n² 次列表元素移动。
     *
     * @param c 用于比较列表元素的比较器。
     *          一个 null 值指示应该使用元素的自然顺序。
     * @since 1.8
     */
    @Override
    @SuppressWarnings("unchecked")
    public void sort(Comparator<? super E> c) {
        final int expectedModCount = modCount;
        Arrays.sort((E[]) elementData, 0, size, c);
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        modCount++;
    }
}

/**
 * 提供对 Arrays 类的支持方法。
 */
class ArraysSupport {
    /**
     * 计算新的数组长度,考虑到溢出。
     * 
     * @param oldLength 旧数组长度
     * @param minGrowth 最小增长
     * @param prefGrowth 首选增长
     * @return 新的数组长度
     * @throws OutOfMemoryError 如果新长度超过最大数组大小
     */
    public static int newLength(int oldLength, int minGrowth, int prefGrowth) {
        // 计算新长度
        int newLength = oldLength + Math.max(minGrowth, prefGrowth);
        // 检查溢出
        if (newLength - Integer.MAX_VALUE > 0) {
            // 计算最小需要的长度
            int minLength = oldLength + minGrowth;
            if (minLength < 0) { // 溢出
                throw new OutOfMemoryError("Required array length too large");
            }
            // 如果最小长度大于最大数组大小,抛出异常
            if (minLength > MAX_ARRAY_SIZE) {
                throw new OutOfMemoryError("Required array length too large");
            }
            // 返回最大数组大小
            return MAX_ARRAY_SIZE;
        }
        // 检查新长度是否小于最小需要的长度
        if (newLength < oldLength + minGrowth) {
            // 如果最小长度溢出,抛出异常
            if (oldLength + minGrowth < 0) {
                throw new OutOfMemoryError("Required array length too large");
            }
            // 返回最小需要的长度
            return oldLength + minGrowth;
        }
        // 返回新长度
        return newLength;
    }

    /**
     * 要分配的最大数组大小。
     */
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
}