ArrayList 阅读源码,了解学习

ArrayList 源码学习

一、了解 ArrayList

1.1 ArrayList 概述

引用百度百科的:

​ ArrayList 就是动态数组,用 MSDN 中的说法,就是 Array 的复杂版本,它提供了动态的增加和减少元素,实现了 Collection 和 List 接口,灵活的设置数组的大小等好处

1.2 ArrayList 定义

image-20201006085601925

从定义可以看出:

  1. ArrayList 是 List 接口的大小可变数组的实现;
  2. ArrayList 实现了所有可选列表操作,并允许 null 元素;
  3. ArrayList 不断添加元素,容量也会自动增长;
  4. ArrayList 是不同步的,线程不安全的;
  5. ArrayList 的 iterator 和 listIterator 方法返回的迭代器是 fail-fast。
1.3 ArrayList 的数据结构

image-20201006091908610

底层的数据结构就是数组,数组元素类型为 Object 类型,即可以存放所有类型数据。对 ArrayList 类的实例的所有操作底层都是基于数组的。

二、ArrayList 源码分析

2.1 ArrayList 继承结构和层次关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1lVkvwq5-1601967575238)(G:/noteImage/image-20201006093520760.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ig84FqSu-1601967575243)(G:/noteImage/image-20201006093539694.png)]

ArrayList 的继承结构:

​ ArrayList extends AbstractList

​ AbstractList extends AbstractCollection

由继承关系和层次关系可以看出:

  1. ArrayList :说明 ArrayList 支持泛型;
  2. 实现 RandomAccess 接口:表明 ArrayList 支持快速随机访问。什么是快速随机访问:可以通过元素的序号快速获取元素对象;
  3. 实现了 Cloneable 接口:可以使用 Object.clone() 方法了;
  4. java.io.Serializable:表明这个类可以被序列化。
2.2 ArrayList 类的常用属性
/**
 * 序列号也就是版本号
 */
private static final long serialVersionUID = 8683452581122892189L;

/**
 * Default initial capacity.
 * 默认容量
 */
private static final int DEFAULT_CAPACITY = 10;

/**
 * Shared empty array instance used for empty instances.
 * 空对象数组
 * 当用户指定该 ArrayList 容量为 0 时,返回该空数组
 */
private static final Object[] EMPTY_ELEMENTDATA = {};

/**
 * Shared empty array instance used for default sized empty instances. We
 * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
 * first element is added.
 * 默认空对象数组
 * 用于默认大小的空实例的共享空数组实例。
 */
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

/**
 * The array buffer into which the elements of the ArrayList are stored.
 * The capacity of the ArrayList is the length of this array buffer. Any
 * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
 * will be expanded to DEFAULT_CAPACITY when the first element is added.
 * 元素数组。ArrayList 是基于数组实现的,用该数组保存数据,ArrayList 的容量就是该数组的长度
 * 值为 elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA 的空 ArrayList 将在添加
 * 第一个元素时扩容为 DEFAULT_CAPACITY
 */
transient Object[] elementData; // non-private to simplify nested class access

/**
 * The size of the ArrayList (the number of elements it contains).
 *
 * @serial ArrayList 实际存储的数据容量,默认为 0
 */
private int size;
2.3 ArrayList 类的构造方法

ArrayList 提供了三种构造方法:

	/**
     * Constructs an empty list with the specified initial capacity.
     * 创建一个有初始容量的、空的 ArrayList
     *
     * @param initialCapacity the initial capacity of the list  list 的初始容量
     * @throws IllegalArgumentException if the specified initial capacity
     *                                  is negative
     *                                  如果初始容量值非法时(小于0)抛出异常
     */
    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            // 将自定义的初始容量大小当成初始化 elementData 的大小
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            // 初始容量等于0,使用默认空对象数组
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            // 如果初始容量小于0,则报非法数据异常
            throw new IllegalArgumentException("Illegal Capacity: " +
                    initialCapacity);
        }
    }

    /**
     * Constructs an empty list with an initial capacity of ten.
     * 构造一个初始容量为 10 的空的 list
     * 无参构造函数
     * 创建一个空的 ArrayList ,此时其内数组缓存区 elementData = {},长度为 0
     * 当元素被第一次添加时,扩容至默认容量 10
     */
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    /**
     * Constructs a list containing the elements of the specified
     * collection, in the order they are returned by the collection's
     * iterator.
     * 创建一个包含 Collection 的 ArrayList
     *
     * @param c the collection whose elements are to be placed into this list
     *          要放入 ArrayList 中的集合,其内元素将会全部添加到新建的 ArrayList 实例中
     * @throws NullPointerException if the specified collection is null  当参数 c 为 null 时抛出异常
     */
    public ArrayList(Collection<? extends E> c) {
        // 将集合转化成 Object 数组
        elementData = c.toArray();
        // 将转化后的 Object 数组的长度赋值给 ArrayList 的 size,闭关判断是否为 0
        if ((size = elementData.length) != 0) {
            // defend against c.toArray (incorrectly) not returning Object[]
            // c.toArray 可能不会返回 Object 数组,详情请参见下面这个链接
            // (see e.g. https://bugs.openjdk.java.net/browse/JDK-6260652)
            if (elementData.getClass() != Object[].class)
                // 若 c.toArray 返回的数组类型不是 Object[],使用 Arrays.copyOf来构建一个大小为 size 的 Object[] 数组
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            // 替换空数组
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

ArrayList 的构造方法就是初始化内部的数组,也就是用来存储数据的容器。

2.4 ArrayList 类的常用方法
2.4.1 get() 方法
/**
 * Returns the element at the specified position in this list.
 * 返回在 ArrayList 中指定位置上的元素
 * @param index index of the element to return 下标为 index 的元素
 * @return the element at the specified position in this list
 * @throws IndexOutOfBoundsException {@inheritDoc}
 */
public E get(int index) {
    // 检查是否越界
    Objects.checkIndex(index, size);
    return elementData(index);
}
/**
 * 返回索引为 index 的元素:数组的随机访问
 * 默认包访问权限
 * @param index
 * @return
 */
@SuppressWarnings("unchecked")
E elementData(int index) {
    return (E) elementData[index];
}

get() 方法很简单,因为底层使用数组结构的,首先判断传过来的下标是否越界,使用的是 Objects 里面的方法判断;

然后直接通过数组的下标找到元素并返回。

2.4.2 set() 方法
	/**
     * Replaces the element at the specified position in this list with
     * the specified element.
     * 将 ArrayList 中指定位置的元素替换为指定的元素
     * @param index   index of the element to replace 索引值
     * @param element element to be stored at the specified position 指定的元素
     * @return the element previously at the specified position 替换前指定位置的元素
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public E set(int index, E element) {
        // 越界检查
        Objects.checkIndex(index, size);
        // 获取指定位置的元素
        E oldValue = elementData(index);
        // 将指定元素替换到指定的位置上
        elementData[index] = element;
        // 返回旧数据
        return oldValue;
    }
2.4.3 add() 方法
  • public boolean add(E e) // 一个参数的

    /**
     * Appends the specified element to the end of this list.
     * 增加指定的元素到 ArrayList 的最后位置
     * @param e element to be appended to this list
     *          要添加到 ArrayList 的元素
     * @return {@code true} (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
        modCount++;
        add(e, elementData, size);
        return true;
    }
    
    /**
     * This helper method split out from add(E) to keep method
     * bytecode size under 35 (the -XX:MaxInlineSize default value),
     * which helps when add(E) is called in a C1-compiled loop.
     *
     * 这个 helper 方法从 add(E) 中分离出来,
     * 使 method bytecode 的大小保持在 35 以下(-XX:MaxInlineSize默认值),
     * 这有助于在 c1 编译循环中调用 add(E)。
     */
    private void add(E e, Object[] elementData, int s) {
        // ArrayList 的实际容量等于数组的长度,就需要进行扩容操作
        if (s == elementData.length)
            elementData = grow();
        // 将指定的元素添加到 ArrayList 的最后位置
        elementData[s] = e;
        // 大小+1
        size = s + 1;
    }
    /**
     * Increases the capacity to ensure that it can hold at least the
     * number of elements specified by the minimum capacity argument.
     * 以新的容量创建一个数组,然后将原数组的数据复制到新创建的数组中
     * 增加容量以确保它至少可以容纳参数指定的元素数量
     * @param minCapacity the desired minimum capacity 指定的最小容量
     * @throws OutOfMemoryError if minCapacity is less than zero 如果容量小于0
     */
    private Object[] grow(int minCapacity) {
        return elementData = Arrays.copyOf(elementData, newCapacity(minCapacity));
    }
    
    private Object[] grow() {
        return grow(size + 1);
    }
    /**
     * Returns a capacity at least as large as the given minimum capacity.
     * Returns the current capacity increased by 50% if that suffices.
     * Will not return a capacity greater than MAX_ARRAY_SIZE unless
     * the given minimum capacity is greater than MAX_ARRAY_SIZE.
     * 真正的将容量扩容
     * 返回的容量至少与给定的最小容量一样大。
     * 如果足够的话,当前的容量增加了 50%。
     * 不会返回大于 MAX_ARRAY_SIZE 的容量,除非给定的最小容量大于 MAX_ARRAY_SIZE
     * @param minCapacity the desired minimum capacity
     * @throws OutOfMemoryError if minCapacity is less than zero 如果容量小于0
     */
    private int newCapacity(int minCapacity) {
        // overflow-conscious code
        // 防止溢出代码
        int oldCapacity = elementData.length;
        // 运算符 >> 是带符号的右移,比如 oldCapacity = 10,则 10 + (10 >> 1) = 15
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        // 如果新的容量小于等于指定的最小容量
        if (newCapacity - minCapacity <= 0) {
            // 如果当前数组是默认的空数组对象
            if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
                // 返回默认容量和指定的最小容量中的最大值
                return Math.max(DEFAULT_CAPACITY, minCapacity);
            if (minCapacity < 0) // overflow,指定的最小容量小于0,抛出异常
                throw new OutOfMemoryError();
            // 返回指定的最小容量
            return minCapacity;
        }
        // 新的容量大于指定的最小容量
        // 如果新容量小于等于最大存储容量,返回新容量,否则进行大容量分配
        return (newCapacity - MAX_ARRAY_SIZE <= 0)
            ? newCapacity
            : hugeCapacity(minCapacity);
    }
    

    执行流程:

  • public void add(int index, E element)// 两个参数的

    /**
     * Inserts the specified element at the specified position in this
     * list. Shifts the element currently at that position (if any) and
     * any subsequent elements to the right (adds one to their indices).
     * 在这个 ArrayList 的指定位置插入指定的元素。
     * 将元素当前的位置(如果有的话)和后续的元素向右移动(在它们的索引中添加一个)。
     * @param index   index at which the specified element is to be inserted
     *                要插入指定元素的索引
     * @param element element to be inserted 要插入的元素
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public void add(int index, E element) {
        // 判断角标是否越界
        rangeCheckForAdd(index);
        modCount++;
        final int s;
        Object[] elementData;
        // ArrayList 的实际容量等于数组的长度,就需要进行扩容操作
        // 将 size 的大小赋值给 s,将这个对象的数组赋值给 elementData
        if ((s = size) == (elementData = this.elementData).length)
            elementData = grow();
        // 第一个是要复制的数组,第二个是从要复制的数组的第几个开始,
        // 第三个是复制到那,四个是复制到的数组第几个开始,最后一个是复制长度
        // 意思就是将 index 之后的元素包括 index 复制到 index+1 之后
        System.arraycopy(elementData, index,
                         elementData, index + 1,
                         s - index);
        // 将指定的元素插入到指定的位置
        elementData[index] = element;
        // 实际大小 +1
        size = s + 1;
    }
    /**
     * A version of rangeCheck used by add and addAll.
     * 添加时检查索引是否越界
     */
    private void rangeCheckForAdd(int index) {
        if (index > size || index < 0)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }
    

    执行流程:和带一个参数的 add() 方法一样,就是最后添加元素不是添加到 ArrayList 的最后位置,而是添加到指定位置。

2.4.4 remove() 方法
  • 通过索引删除指定位置的元素

    /**
     * Removes the element at the specified position in this list.
     * Shifts any subsequent elements to the left (subtracts one from their
     * indices).
     * 移除 ArrayList 中指定位置的元素。将后面的元素向左移动(从它们的下标中减去1)
     * @param index the index of the element to be removed 指定的位置
     * @return the element that was removed from the list  被移除的元素
     * @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;
    }
    /**
     * Private remove method that skips bounds checking and does not
     * return the value removed.
     * 跳过边界检查且不返回已删除值的私有移除方法。
     */
    private void fastRemove(Object[] es, int i) {
        modCount++;
        final int newSize;
        if ((newSize = size - 1) > i)// 要移动的长度
            // 将 i+1 及其后面的元素复制到 i 及其后面的下标上
            System.arraycopy(es, i + 1, es, i, newSize - i);
        // 将最后一个位置置为空
        es[size = newSize] = null;
    }
    

    执行流程:

    1. 判断数组下标是否越界;
    2. 修改次数自增(modCount 是用来检测 fail-fast 的标志);
    3. 计算要移动的长度;
    4. 移动元素,也就是复制;
    5. 将最后一个位置置空,也就是 size 的位置为 null;
    6. 返回被删除的元素。
  • 通过对象删除指定元素

    /**
     * Removes the first occurrence of the specified element from this list,
     * if it is present.  If the list does not contain the element, it is
     * unchanged.  More formally, removes the element with the lowest index
     * {@code i} such that
     * {@code Objects.equals(o, get(i))}
     * (if such an element exists).  Returns {@code true} if this list
     * contained the specified element (or equivalently, if this list
     * changed as a result of the call).
     * 如果指定元素出现,移除这个 ArrayList 中第一次出现的元素。
     * 如果 ArrayList 不包含这个元素,ArrayList 不会改变。
     * @param o element to be removed from this list, if present 要删除的元素
     * @return {@code true} if this list contained the specified element 如果包含指定的元素返回 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;
    }
    
  • removeRange(int fromIndex, int toIndex)

    /**
     * Removes from this list all of the elements whose index is between
     * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.
     * Shifts any succeeding elements to the left (reduces their index).
     * This call shortens the list by {@code (toIndex - fromIndex)} elements.
     * (If {@code toIndex==fromIndex}, this operation has no effect.)
     * 从 ArrayList 中移除索引在 fromIndex 和 toIndex 之间所有的元素
     * 将所有元素向左移动(toIndex-fromIndex)个元素
     * 如果 (toIndex==fromIndex)这个操作没有影响
     * @throws IndexOutOfBoundsException if {@code fromIndex} or
     *                                   {@code 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);
    }
    
    /**
     * Erases the gap from lo to hi, by sliding down following elements.
     * 通过向下滑动以下元素来消除从lo到hi的间隙
     */
    private void shiftTailOverGap(Object[] es, int lo, int hi) {
        // size-hi 要移动的数量
        System.arraycopy(es, hi, es, lo, size - hi);
        // 将失效元素置空
        for (int to = size, i = (size -= hi - lo); i < to; i++)
            es[i] = null;
    }
    
  • removeAll(Collection<?> c)

    /**
     * Removes from this list all of its elements that are contained in the
     * specified collection.
     * 从此 ArrayList 中删除指定的集合中包含的所有元素。
     * @param c collection containing elements to be removed from this list
     *          要从 list 中删除的元素的集合
     * @return {@code true} if this list changed as a result of the call
     * @throws ClassCastException   if the class of an element of this list
     *                              is incompatible with the specified collection
     *                              (<a href="Collection.html#optional-restrictions">optional</a>)
     * @throws NullPointerException if this list contains a null element and the
     *                              specified collection does not permit null elements
     *                              (<a href="Collection.html#optional-restrictions">optional</a>),
     *                              or if the specified collection is null
     * @see Collection#contains(Object)
     */
    public boolean removeAll(Collection<?> c) {
        return batchRemove(c, false, 0, size);
    }
    /**
     * 批处理移除
     * @param c 要移除的集合
     * @param complement 是否是补集
     *                   如果true:移除list中除了c集合中的所有元素
     *                   如果false:移除list中 c集合中的元素
     * @param from
     * @param end
     * @return
     */
    boolean batchRemove(Collection<?> c, boolean complement,
                        final int from, final int end) {
        // 检查要移除的集合不为空
        Objects.requireNonNull(c);
        final Object[] es = elementData;
        int r;
        // Optimize for initial run of survivors
        for (r = from; ; r++) {
            if (r == end)
                return false;
            if (c.contains(es[r]) != complement)
                break;
        }
        int w = r++;
        try {
            for (Object e; r < end; r++)
                if (c.contains(e = es[r]) == complement)
                    es[w++] = e;
        } catch (Throwable ex) {
            // Preserve behavioral compatibility with AbstractCollection,
            // even if c.contains() throws.
            System.arraycopy(es, r, es, w, end - r);
            w += end - r;
            throw ex;
        } finally {
            modCount += end - w;
            shiftTailOverGap(es, w, end);
        }
        return true;
    }
    
  • retainAll(Collection<?> c)

    public boolean retainAll(Collection<?> c) {
        return batchRemove(c, true, 0, size);
    } 
    
2.4.5 indexOf() 和 lastIndexOf() 方法
/**
 * Returns the index of the first occurrence of the specified element
 * in this list, or -1 if this list does not contain the element.
 * More formally, returns the lowest index {@code i} such that
 * {@code Objects.equals(o, get(i))},
 * or -1 if there is no such index.
 *
 * 返回 ArrayList 中指定元素的第一个匹配项的索引,如果 ArrayList 不包含该元素,返回 -1
 * 更准确的说,返回最低索引 i ,以便 o.equals(es[i]),如果没有这样的索引,返回 -1
 */
public int indexOf(Object o) {
    return indexOfRange(o, 0, size);
}

/**
 * 顺序查找,返回元素的z最低索引值(最先出现的索引位置)
 * @param o
 * @param start
 * @param end
 * @return 存在 ? 最低索引值 : -1
 */
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;
}

/**
 * Returns the index of the last occurrence of the specified element
 * in this list, or -1 if this list does not contain the element.
 * More formally, returns the highest index {@code i} such that
 * {@code Objects.equals(o, get(i))},
 * or -1 if there is no such index.
 *
 * 返回 ArrayList 中指定元素的最后一个匹配项的索引,如果 ArrayList 不包含该元素,返回 -1
 * 更准确的说,返回最高索引 i ,以便 o.equals(es[i]),如果没有这样的索引,返回 -1
 */
public int lastIndexOf(Object o) {
    return lastIndexOfRange(o, 0, size);
}

/**
 * 逆序查找
 * @param o
 * @param start
 * @param end
 * @return 存在 ? 最高索引 : -1
 */
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;
}
2.5 ArrayList 类的完整解读
package com.xiaoyu.util;

import java.util.*;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;

/**
 * Resizable-array implementation of the {@code List} interface.  Implements
 * all optional list operations, and permits all elements, including
 * {@code null}.  In addition to implementing the {@code List} interface,
 * this class provides methods to manipulate the size of the array that is
 * used internally to store the list.  (This class is roughly equivalent to
 * {@code Vector}, except that it is unsynchronized.)
 *
 * <p>The {@code size}, {@code isEmpty}, {@code get}, {@code set},
 * {@code iterator}, and {@code listIterator} operations run in constant
 * time.  The {@code add} operation runs in <i>amortized constant time</i>,
 * that is, adding n elements requires O(n) time.  All of the other operations
 * run in linear time (roughly speaking).  The constant factor is low compared
 * to that for the {@code LinkedList} implementation.
 *
 * <p>Each {@code ArrayList} instance has a <i>capacity</i>.  The capacity is
 * the size of the array used to store the elements in the list.  It is always
 * at least as large as the list size.  As elements are added to an ArrayList,
 * its capacity grows automatically.  The details of the growth policy are not
 * specified beyond the fact that adding an element has constant amortized
 * time cost.
 *
 * <p>An application can increase the capacity of an {@code ArrayList} instance
 * before adding a large number of elements using the {@code ensureCapacity}
 * operation.  This may reduce the amount of incremental reallocation.
 *
 * <p><strong>Note that this implementation is not synchronized.</strong>
 * If multiple threads access an {@code ArrayList} instance concurrently,
 * and at least one of the threads modifies the list structurally, it
 * <i>must</i> be synchronized externally.  (A structural modification is
 * any operation that adds or deletes one or more elements, or explicitly
 * resizes the backing array; merely setting the value of an element is not
 * a structural modification.)  This is typically accomplished by
 * synchronizing on some object that naturally encapsulates the list.
 * <p>
 * If no such object exists, the list should be "wrapped" using the
 * {@link Collections#synchronizedList Collections.synchronizedList}
 * method.  This is best done at creation time, to prevent accidental
 * unsynchronized access to the list:<pre>
 *   List list = Collections.synchronizedList(new ArrayList(...));</pre>
 *
 * <p id="fail-fast">
 * The iterators returned by this class's {@link #iterator() iterator} and
 * {@link #listIterator(int) listIterator} methods are <em>fail-fast</em>:
 * if the list is structurally modified at any time after the iterator is
 * created, in any way except through the iterator's own
 * {@link ListIterator#remove() remove} or
 * {@link ListIterator#add(Object) add} methods, the iterator will throw a
 * {@link ConcurrentModificationException}.  Thus, in the face of
 * concurrent modification, the iterator fails quickly and cleanly, rather
 * than risking arbitrary, non-deterministic behavior at an undetermined
 * time in the future.
 *
 * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
 * as it is, generally speaking, impossible to make any hard guarantees in the
 * presence of unsynchronized concurrent modification.  Fail-fast iterators
 * throw {@code ConcurrentModificationException} on a best-effort basis.
 * Therefore, it would be wrong to write a program that depended on this
 * exception for its correctness:  <i>the fail-fast behavior of iterators
 * should be used only to detect bugs.</i>
 *
 * <p>This class is a member of the
 * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
 * Java Collections Framework</a>.
 *
 * @param <E> the type of elements in this list
 * @author Josh Bloch
 * @author Neal Gafter
 * @see Collection
 * @see List
 * @see LinkedList
 * @see Vector
 * @since 1.2
 */
public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
    /**
     * 序列号也就是版本号
     */
    private static final long serialVersionUID = 8683452581122892189L;

    /**
     * Default initial capacity.
     * 默认容量
     */
    private static final int DEFAULT_CAPACITY = 10;

    /**
     * Shared empty array instance used for empty instances.
     * 空对象数组
     * 当用户指定该 ArrayList 容量为 0 时,返回该空数组
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};

    /**
     * Shared empty array instance used for default sized empty instances. We
     * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
     * first element is added.
     * 默认空对象数组
     * 用于默认大小的空实例的共享空数组实例。
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    /**
     * The array buffer into which the elements of the ArrayList are stored.
     * The capacity of the ArrayList is the length of this array buffer. Any
     * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
     * will be expanded to DEFAULT_CAPACITY when the first element is added.
     * 元素数组。ArrayList 是基于数组实现的,用该数组保存数据,ArrayList 的容量就是该数组的长度
     * 值为 elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA 的空 ArrayList 将在添加
     * 第一个元素时扩容为 DEFAULT_CAPACITY
     */
    transient Object[] elementData; // non-private to simplify nested class access

    /**
     * The size of the ArrayList (the number of elements it contains).
     *
     * @serial ArrayList 实际存储的数据容量,默认为 0
     */
    private int size;

    /**
     * Constructs an empty list with the specified initial capacity.
     * 创建一个有初始容量的、空的 ArrayList
     *
     * @param initialCapacity the initial capacity of the list  list 的初始容量
     * @throws IllegalArgumentException if the specified initial capacity
     *                                  is negative
     *                                  如果初始容量值非法时(小于0)抛出异常
     */
    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            // 将自定义的初始容量大小当成初始化 elementData 的大小
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            // 初始容量等于0,使用默认空对象数组
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            // 如果初始容量小于0,则报非法数据异常
            throw new IllegalArgumentException("Illegal Capacity: " +
                    initialCapacity);
        }
    }

    /**
     * Constructs an empty list with an initial capacity of ten.
     * 构造一个初始容量为 10 的空的 list
     * 无参构造函数
     * 创建一个空的 ArrayList ,此时其内数组缓存区 elementData = {},长度为 0
     * 当元素被第一次添加时,扩容至默认容量 10
     */
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    /**
     * Constructs a list containing the elements of the specified
     * collection, in the order they are returned by the collection's
     * iterator.
     * 创建一个包含 Collection 的 ArrayList
     *
     * @param c the collection whose elements are to be placed into this list
     *          要放入 ArrayList 中的集合,其内元素将会全部添加到新建的 ArrayList 实例中
     * @throws NullPointerException if the specified collection is null  当参数 c 为 null 时抛出异常
     */
    public ArrayList(Collection<? extends E> c) {
        // 将集合转化成 Object 数组
        elementData = c.toArray();
        // 将转化后的 Object 数组的长度赋值给 ArrayList 的 size,闭关判断是否为 0
        if ((size = elementData.length) != 0) {
            // defend against c.toArray (incorrectly) not returning Object[]
            // c.toArray 可能不会返回 Object 数组,详情请参见下面这个链接
            // (see e.g. https://bugs.openjdk.java.net/browse/JDK-6260652)
            if (elementData.getClass() != Object[].class)
                // 若 c.toArray 返回的数组类型不是 Object[],使用 Arrays.copyOf来构建一个大小为 size 的 Object[] 数组
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            // 替换空数组
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

    /**
     * Trims the capacity of this {@code ArrayList} instance to be the
     * list's current size.  An application can use this operation to minimize
     * the storage of an {@code ArrayList} instance.
     * 将数组缓存区大小调整到实际 ArrayList 存储元素的大小,即 elementData = Arrays.copyOf(elementData,size)
     * 这个方法由用户自己手动调用,以减少空间资源浪费的目的
     */
    public void trimToSize() {
        // modCount 是 AbstractList 的属性
        // modCount有什么作用?
        // 记录修改次数,
        modCount++;
        // 实际大小小于数组缓存区大小
        if (size < elementData.length) {
            // 这里执行的是elementData = ((size == 0) ? EMPTY_ELEMENTDATA : Arrays.copyOf(elementData, size))
            // 调整数组缓存区 elementData 变为实际存储大小 Arrays.copyOf(elementData, size)
            // 如果 size 为 0,实际存储为 EMPTY_ELEMENTDATA,如果有数据就是 Arrays.copyOf(elementData, size)
            elementData = (size == 0)
                    ? EMPTY_ELEMENTDATA
                    : Arrays.copyOf(elementData, size);
        }
    }

    /**
     * Increases the capacity of this {@code ArrayList} instance, if
     * necessary, to ensure that it can hold at least the number of elements
     * specified by the minimum capacity argument.
     * 指定 ArrayList 的容量
     * @param minCapacity the desired minimum capacity
     *                    指定的最小容量
     */
    public void ensureCapacity(int minCapacity) {
        // 如果最小容量大于数组缓存区当前的长度且
        // (数组不等于默认空数组且用户指定的最小容量大于最小扩充容量)
        if (minCapacity > elementData.length
                && !(elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
                && minCapacity <= DEFAULT_CAPACITY)) {
            // 修改次数自增,这个变量主要是用来实现 fail-fast 机制的
            modCount++;
            // 进行扩容操作
            grow(minCapacity);
        }
    }

    /**
     * The maximum size of array to allocate (unless necessary).
     * Some VMs reserve some header words in an array.
     * Attempts to allocate larger arrays may result in
     * OutOfMemoryError: Requested array size exceeds VM limit
     *
     * 数组缓存区最大存储容量,数组分配的最大大小
     * 一些虚拟机(VM)在数组中保留一些数据(头字)
     * 尝试分配较大的数组可能会导致 OutOfMemoryError:请求的数组大小超过 VM 限制
     */
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    /**
     * Increases the capacity to ensure that it can hold at least the
     * number of elements specified by the minimum capacity argument.
     * 以新的容量创建一个数组,然后将原数组的数据复制到新创建的数组中
     * 增加容量以确保它至少可以容纳参数指定的元素数量
     * @param minCapacity the desired minimum capacity 指定的最小容量
     * @throws OutOfMemoryError if minCapacity is less than zero 如果容量小于0
     */
    private Object[] grow(int minCapacity) {
        return elementData = Arrays.copyOf(elementData,
                newCapacity(minCapacity));
    }

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

    /**
     * Returns a capacity at least as large as the given minimum capacity.
     * Returns the current capacity increased by 50% if that suffices.
     * Will not return a capacity greater than MAX_ARRAY_SIZE unless
     * the given minimum capacity is greater than MAX_ARRAY_SIZE.
     * 真正的将容量扩容
     * 返回的容量至少与给定的最小容量一样大。
     * 如果足够的话,当前的容量增加了 50%。
     * 不会返回大于 MAX_ARRAY_SIZE 的容量,除非给定的最小容量大于 MAX_ARRAY_SIZE
     * @param minCapacity the desired minimum capacity
     * @throws OutOfMemoryError if minCapacity is less than zero 如果容量小于0
     */
    private int newCapacity(int minCapacity) {
        // overflow-conscious code
        // 防止溢出代码
        int oldCapacity = elementData.length;
        // 运算符 >> 是带符号的右移,比如 oldCapacity = 10,则 10 + (10 >> 1) = 15
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        // 如果新的容量小于等于指定的最小容量
        if (newCapacity - minCapacity <= 0) {
            // 如果当前数组是默认的空数组对象
            if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
                // 返回默认容量和指定的最小容量中的最大值
                return Math.max(DEFAULT_CAPACITY, minCapacity);
            if (minCapacity < 0) // overflow,指定的最小容量小于0,抛出异常
                throw new OutOfMemoryError();
            // 返回指定的最小容量
            return minCapacity;
        }
        // 新的容量大于指定的最小容量
        // 如果新容量小于等于最大存储容量,返回新容量,否则进行大容量分配
        return (newCapacity - MAX_ARRAY_SIZE <= 0)
                ? newCapacity
                : hugeCapacity(minCapacity);
    }

    /**
     * 私有方法:大容量分配,最大分配:Integer.MAX_VALUE
     * @param minCapacity
     * @return
     */
    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE)
                ? Integer.MAX_VALUE
                : MAX_ARRAY_SIZE;
    }

    /**
     * Returns the number of elements in this list.
     * 返回 ArrayList 中元素的数量
     * @return the number of elements in this list
     */
    public int size() {
        return size;
    }

    /**
     * Returns {@code true} if this list contains no elements.
     * 如果 ArrayList 为空,返回 true
     * @return {@code true} if this list contains no elements
     */
    public boolean isEmpty() {
        return size == 0;
    }

    /**
     * Returns {@code true} if this list contains the specified element.
     * More formally, returns {@code true} if and only if this list contains
     * at least one element {@code e} such that
     * {@code Objects.equals(o, e)}.
     * 如果 ArrayList 中包含指定元素,返回 true
     * 更准确的说,当且仅当 ArrayList 中包含至少一个元素 o 时返回 true
     * @param o element whose presence in this list is to be tested
     * @return {@code true} if this list contains the specified element
     */
    public boolean contains(Object o) {
        // 根据 indexOf() 的值(索引值)来判断,大于等于 0 就包含
        // 等于 0 的情况不能漏掉,因为数组的下标从 0 开始
        return indexOf(o) >= 0;
    }

    /**
     * Returns the index of the first occurrence of the specified element
     * in this list, or -1 if this list does not contain the element.
     * More formally, returns the lowest index {@code i} such that
     * {@code Objects.equals(o, get(i))},
     * or -1 if there is no such index.
     *
     * 返回 ArrayList 中指定元素的第一个匹配项的索引,如果 ArrayList 不包含该元素,返回 -1
     * 更准确的说,返回最低索引 i ,以便 o.equals(es[i]),如果没有这样的索引,返回 -1
     */
    public int indexOf(Object o) {
        return indexOfRange(o, 0, size);
    }

    /**
     * 顺序查找,返回元素的z最低索引值(最先出现的索引位置)
     * @param o
     * @param start
     * @param end
     * @return 存在 ? 最低索引值 : -1
     */
    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;
    }

    /**
     * Returns the index of the last occurrence of the specified element
     * in this list, or -1 if this list does not contain the element.
     * More formally, returns the highest index {@code i} such that
     * {@code Objects.equals(o, get(i))},
     * or -1 if there is no such index.
     *
     * 返回 ArrayList 中指定元素的最后一个匹配项的索引,如果 ArrayList 不包含该元素,返回 -1
     * 更准确的说,返回最高索引 i ,以便 o.equals(es[i]),如果没有这样的索引,返回 -1
     */
    public int lastIndexOf(Object o) {
        return lastIndexOfRange(o, 0, size);
    }

    /**
     * 逆序查找
     * @param o
     * @param start
     * @param end
     * @return 存在 ? 最高索引 : -1
     */
    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;
    }

    /**
     * Returns a shallow copy of this {@code ArrayList} instance.  (The
     * elements themselves are not copied.)
     * 返回这个{@code ArrayList}实例的浅拷贝。(元素本身不会被复制。)
     * @return a clone of this {@code ArrayList} instance 一个克隆的 ArrayList 实例(深度复制的结果)
     */
    public Object clone() {
        try {
            // Object 的克隆方法:会复制对象本身及其内所有基本类型成员和 String 类型成员,但不会复制对象成员和引用对象
            ArrayList<?> v = (ArrayList<?>) super.clone();
            // 对需要进行复制的引用变量进行独立的拷贝:将存储的元素移到新的 ArrayList 中
            v.elementData = Arrays.copyOf(elementData, size);
            v.modCount = 0;
            return v;
        } catch (CloneNotSupportedException e) {
            // this shouldn't happen, since we are Cloneable
            // 这不应该发生,因为我们是可克隆的
            throw new InternalError(e);
        }
    }

    /**
     * Returns an array containing all of the elements in this list
     * in proper sequence (from first to last element).
     *
     * <p>The returned array will be "safe" in that no references to it are
     * maintained by this list.  (In other words, this method must allocate
     * a new array).  The caller is thus free to modify the returned array.
     *
     * <p>This method acts as bridge between array-based and collection-based
     * APIs.
     *
     * @return an array containing all of the elements in this list in
     * proper sequence
     *
     * 返回一个Object数组,这个数组包含 ArrayList 中的所有元素,并且顺序一致(从第一个元素到最后一个元素)
     * 对返回的数组进行操作时安全的,不会影响 ArrayList,也就是说这个方法必须分配一个新的数组,调用中可以自由的修改返回的数组
     * 这个方法充当基于数组和基于集合 api 之间的桥梁
     */
    public Object[] toArray() {
        return Arrays.copyOf(elementData, size);
    }

    /**
     * Returns an array containing all of the elements in this list in proper
     * sequence (from first to last element); the runtime type of the returned
     * array is that of the specified array.  If the list fits in the
     * specified array, it is returned therein.  Otherwise, a new array is
     * allocated with the runtime type of the specified array and the size of
     * this list.
     *
     * <p>If the list fits in the specified array with room to spare
     * (i.e., the array has more elements than the list), the element in
     * the array immediately following the end of the collection is set to
     * {@code null}.  (This is useful in determining the length of the
     * list <i>only</i> if the caller knows that the list does not contain
     * any null elements.)
     * 返回一个包含 ArrayList 中所有元素的数组(从第一个元素到最后一个元素)
     * 返回数组的运行时类型是指定的数组类型,如果 ArrayList 与数组匹配,则返回 ArrayList;否则
     * 将为新数组分配指定数组的运行时类型和这个 ArrayList 的大小
     * @param a the array into which the elements of the list are to
     *          be stored, if it is big enough; otherwise, a new array of the
     *          same runtime type is allocated for this purpose.
     *          需要存储 list 中元素的数组
     *          若 a.length >= list.size,则将 list 中的元素按顺序存入 a 中,
     *          然后 a[list.size] = null, a[list.size + 1] 及其后的元素依旧是 a 的元素;
     *          否则,将返回包含list 所有元素且数组长度等于 list 中元素个数的数组
     * @return an array containing the elements of the list
     * @throws ArrayStoreException  if the runtime type of the specified array
     *                              is not a supertype of the runtime type of every element in
     *                              this list
     *                              当 a.getClass() != list 中存储元素的类型时
     * @throws NullPointerException if the specified array is null 当 a 为 null 时
     */
    @SuppressWarnings("unchecked")
    public <T> T[] toArray(T[] a) {
        // 如果数组 a 的大小小于 ArrayList 的元素个数,则新建一个 T[] 数组
        // 数组大小时 ArrayList 的元素个数,并把 ArrayList 全部拷贝到新的数组中
        if (a.length < size)
            // Make a new array of a's runtime type, but my contents:
            return (T[]) Arrays.copyOf(elementData, size, a.getClass());
        // 如果数组 a 的大小大于 ArrayList 的元素个数,将 ArrayList 中的元素全部拷贝到数组 a 中
        System.arraycopy(elementData, 0, a, 0, size);
        if (a.length > size)
            a[size] = null;
        return a;
    }

    // Positional Access Operations  位置访问操作

    /**
     * 返回索引为 index 的元素:数组的随机访问
     * 默认包访问权限
     * @param index
     * @return
     */
    @SuppressWarnings("unchecked")
    E elementData(int index) {
        return (E) elementData[index];
    }

    @SuppressWarnings("unchecked")
    static <E> E elementAt(Object[] es, int index) {
        return (E) es[index];
    }

    /**
     * Returns the element at the specified position in this list.
     * 返回在 ArrayList 中指定位置上的元素
     * @param index index of the element to return 下标为 index 的元素
     * @return the element at the specified position in this list
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public E get(int index) {
        // 检查是否越界
        Objects.checkIndex(index, size);
        return elementData(index);
    }

    /**
     * Replaces the element at the specified position in this list with
     * the specified element.
     * 将 ArrayList 中指定位置的元素替换为指定的元素
     * @param index   index of the element to replace 索引值
     * @param element element to be stored at the specified position 指定的元素
     * @return the element previously at the specified position 替换前指定位置的元素
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public E set(int index, E element) {
        // 越界检查
        Objects.checkIndex(index, size);
        // 获取指定位置的元素
        E oldValue = elementData(index);
        // 将指定元素替换到指定的位置上
        elementData[index] = element;
        // 返回旧数据
        return oldValue;
    }

    /**
     * This helper method split out from add(E) to keep method
     * bytecode size under 35 (the -XX:MaxInlineSize default value),
     * which helps when add(E) is called in a C1-compiled loop.
     *
     * 这个 helper 方法从 add(E) 中分离出来,
     * 使 method bytecode 的大小保持在 35 以下(-XX:MaxInlineSize默认值),
     * 这有助于在 c1 编译循环中调用 add(E)。
     */
    private void add(E e, Object[] elementData, int s) {
        // ArrayList 的实际容量等于数组的长度,就需要进行扩容操作
        if (s == elementData.length)
            elementData = grow();
        // 将指定的元素添加到 ArrayList 的最后位置
        elementData[s] = e;
        // 大小+1
        size = s + 1;
    }

    /**
     * Appends the specified element to the end of this list.
     * 增加指定的元素到 ArrayList 的最后位置
     * @param e element to be appended to this list
     *          要添加到 ArrayList 的元素
     * @return {@code true} (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
        modCount++;
        add(e, elementData, size);
        return true;
    }

    /**
     * Inserts the specified element at the specified position in this
     * list. Shifts the element currently at that position (if any) and
     * any subsequent elements to the right (adds one to their indices).
     * 在这个 ArrayList 的指定位置插入指定的元素。
     * 将元素当前的位置(如果有的话)和后续的元素向右移动(在它们的索引中添加一个)。
     * @param index   index at which the specified element is to be inserted
     *                要插入指定元素的索引
     * @param element element to be inserted 要插入的元素
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public void add(int index, E element) {
        // 判断角标是否越界
        rangeCheckForAdd(index);
        modCount++;
        final int s;
        Object[] elementData;
        // ArrayList 的实际容量等于数组的长度,就需要进行扩容操作
        // 将 size 的大小赋值给 s,将这个对象的数组赋值给 elementData
        if ((s = size) == (elementData = this.elementData).length)
            elementData = grow();
        // 第一个是要复制的数组,第二个是从要复制的数组的第几个开始,
        // 第三个是复制到那,四个是复制到的数组第几个开始,最后一个是复制长度
        // 意思就是将 index 之后的元素包括 index 复制到 index+1 之后
        System.arraycopy(elementData, index,
                elementData, index + 1,
                s - index);
        // 将指定的元素插入到指定的位置
        elementData[index] = element;
        // 实际大小 +1
        size = s + 1;
    }

    /**
     * Removes the element at the specified position in this list.
     * Shifts any subsequent elements to the left (subtracts one from their
     * indices).
     * 移除 ArrayList 中指定位置的元素。将后面的元素向左移动(从它们的下标中减去1)
     * @param index the index of the element to be removed 指定的位置
     * @return the element that was removed from the list  被移除的元素
     * @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;
    }

    /**
     * {@inheritDoc}
     */
    public boolean equals(Object o) {
        if (o == this) {
            return true;
        }

        if (!(o instanceof List)) {
            return false;
        }

        final int expectedModCount = modCount;
        // ArrayList can be subclassed and given arbitrary behavior, but we can
        // still deal with the common case where o is ArrayList precisely
        boolean equal = (o.getClass() == ArrayList.class)
                ? equalsArrayList((ArrayList<?>) o)
                : equalsRange((List<?>) o, 0, size);

        checkForComodification(expectedModCount);
        return equal;
    }

    boolean equalsRange(List<?> other, int from, int to) {
        final Object[] es = elementData;
        if (to > es.length) {
            throw new ConcurrentModificationException();
        }
        var oit = other.iterator();
        for (; from < to; from++) {
            if (!oit.hasNext() || !Objects.equals(es[from], oit.next())) {
                return false;
            }
        }
        return !oit.hasNext();
    }

    private boolean equalsArrayList(ArrayList<?> other) {
        final int otherModCount = other.modCount;
        final int s = size;
        boolean equal;
        if (equal = (s == other.size)) {
            final Object[] otherEs = other.elementData;
            final Object[] es = elementData;
            if (s > es.length || s > otherEs.length) {
                throw new ConcurrentModificationException();
            }
            for (int i = 0; i < s; i++) {
                if (!Objects.equals(es[i], otherEs[i])) {
                    equal = false;
                    break;
                }
            }
        }
        other.checkForComodification(otherModCount);
        return equal;
    }

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

    /**
     * {@inheritDoc}
     */
    public int hashCode() {
        int expectedModCount = modCount;
        int hash = hashCodeRange(0, size);
        checkForComodification(expectedModCount);
        return hash;
    }

    int hashCodeRange(int from, int to) {
        final Object[] es = elementData;
        if (to > es.length) {
            throw new ConcurrentModificationException();
        }
        int hashCode = 1;
        for (int i = from; i < to; i++) {
            Object e = es[i];
            hashCode = 31 * hashCode + (e == null ? 0 : e.hashCode());
        }
        return hashCode;
    }

    /**
     * Removes the first occurrence of the specified element from this list,
     * if it is present.  If the list does not contain the element, it is
     * unchanged.  More formally, removes the element with the lowest index
     * {@code i} such that
     * {@code Objects.equals(o, get(i))}
     * (if such an element exists).  Returns {@code true} if this list
     * contained the specified element (or equivalently, if this list
     * changed as a result of the call).
     * 如果指定元素出现,移除这个 ArrayList 中第一次出现的元素。
     * 如果 ArrayList 不包含这个元素,ArrayList 不会改变。
     * @param o element to be removed from this list, if present 要删除的元素
     * @return {@code true} if this list contained the specified element 如果包含指定的元素返回 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;
    }

    /**
     * Private remove method that skips bounds checking and does not
     * return the value removed.
     * 跳过边界检查且不返回已删除值的私有移除方法。
     */
    private void fastRemove(Object[] es, int i) {
        modCount++;
        final int newSize;
        if ((newSize = size - 1) > i)// 要移动的长度
            // 将 i+1 及其后面的元素复制到 i 及其后面的下标上
            System.arraycopy(es, i + 1, es, i, newSize - i);
        // 将最后一个位置置为空
        es[size = newSize] = null;
    }

    /**
     * Removes all of the elements from this list.  The list will
     * be empty after this call returns.
     * 从此 ArrayList 删除所有元素,这个方法调用后,ArrayList 为空
     */
    public void clear() {
        modCount++;
        final Object[] es = elementData;
        for (int to = size, i = size = 0; i < to; i++)
            es[i] = null;
    }

    /**
     * Appends all of the elements in the specified collection to the end of
     * this list, in the order that they are returned by the
     * specified collection's Iterator.  The behavior of this operation is
     * undefined if the specified collection is modified while the operation
     * is in progress.  (This implies that the behavior of this call is
     * undefined if the specified collection is this list, and this
     * list is nonempty.)
     * 将指定集合中的所有元素添加到这个 ArrayList 的末尾,并按指定集合的 Iterator 返回的顺序进行添加
     * 该方法没有加锁,当一个线程正在将 c 中的元素加入 list 中,但同时有另一个线程在更改 c 中的元素,可能会有问题
     * @param c collection containing elements to be added to this list
     *          要追加的集合
     * @return {@code true} if this list changed as a result of the call 如果 ArrayList 改变返回 true
     * @throws NullPointerException if the specified collection is 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 (numNew > (elementData = this.elementData).length - (s = size))
            // 扩容
            elementData = grow(s + numNew);
        System.arraycopy(a, 0, elementData, s, numNew);
        size = s + numNew;
        return true;
    }

    /**
     * Inserts all of the elements in the specified collection into this
     * list, starting at the specified position.  Shifts the element
     * currently at that position (if any) and any subsequent elements to
     * the right (increases their indices).  The new elements will appear
     * in the list in the order that they are returned by the
     * specified collection's iterator.
     * 从指定位置开始,将指定集合中所有元素插入这个 ArrayList 中。
     * 将当前位置的元素(如果有)和任何后续元素后移。
     * 新元素将按指定集合的迭代器返回的顺序显示在列表中。
     * 不会覆盖在 index 位置原有的值
     * @param index index at which to insert the first element from the
     *              specified collection
     *              插入指定集合的索引
     * @param c     collection containing elements to be added to this list
     *              需要添加的集合
     * @return {@code true} if this list changed as a result of the call  如果 ArrayList 改变返回 true
     * @throws IndexOutOfBoundsException {@inheritDoc}
     * @throws NullPointerException      if the specified collection is null
     */
    public boolean addAll(int index, Collection<? extends E> c) {
        rangeCheckForAdd(index);

        // 将 list 直接转为 Object[] 数组
        Object[] a = c.toArray();
        modCount++;
        int numNew = a.length;// 要添加集合的元素数量
        if (numNew == 0)
            return false;
        Object[] elementData;
        final int s;
        // 扩容判断
        if (numNew > (elementData = this.elementData).length - (s = size))
            elementData = grow(s + numNew);

        int numMoved = s - index;// list 中要移动的数量
        if (numMoved > 0)
            System.arraycopy(elementData, index,
                    elementData, index + numNew,
                    numMoved);
        System.arraycopy(a, 0, elementData, index, numNew);
        size = s + numNew;
        return true;
    }

    /**
     * Removes from this list all of the elements whose index is between
     * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.
     * Shifts any succeeding elements to the left (reduces their index).
     * This call shortens the list by {@code (toIndex - fromIndex)} elements.
     * (If {@code toIndex==fromIndex}, this operation has no effect.)
     * 从 ArrayList 中移除索引在 fromIndex 和 toIndex 之间所有的元素
     * 将所有元素向左移动(toIndex-fromIndex)个元素
     * 如果 (toIndex==fromIndex)这个操作没有影响
     * @throws IndexOutOfBoundsException if {@code fromIndex} or
     *                                   {@code 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);
    }

    /**
     * Erases the gap from lo to hi, by sliding down following elements.
     * 通过向下滑动以下元素来消除从lo到hi的间隙
     */
    private void shiftTailOverGap(Object[] es, int lo, int hi) {
        // size-hi 要移动的数量
        System.arraycopy(es, hi, es, lo, size - hi);
        // 将失效元素置空
        for (int to = size, i = (size -= hi - lo); i < to; i++)
            es[i] = null;
    }

    /**
     * A version of rangeCheck used by add and addAll.
     * 添加时检查索引是否越界
     */
    private void rangeCheckForAdd(int index) {
        if (index > size || index < 0)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    /**
     * Constructs an IndexOutOfBoundsException detail message.
     * Of the many possible refactorings of the error handling code,
     * this "outlining" performs best with both server and client VMs.
     * 构建IndexOutOfBoundsException详细消息
     */
    private String outOfBoundsMsg(int index) {
        return "Index: " + index + ", Size: " + size;
    }

    /**
     * A version used in checking (fromIndex > toIndex) condition
     * 用于检查(fromIndex> toIndex)条件的版本
     */
    private static String outOfBoundsMsg(int fromIndex, int toIndex) {
        return "From Index: " + fromIndex + " > To Index: " + toIndex;
    }

    /**
     * Removes from this list all of its elements that are contained in the
     * specified collection.
     * 从此 ArrayList 中删除指定的集合中包含的所有元素。
     * @param c collection containing elements to be removed from this list
     *          要从 list 中删除的元素的集合
     * @return {@code true} if this list changed as a result of the call
     * @throws ClassCastException   if the class of an element of this list
     *                              is incompatible with the specified collection
     *                              (<a href="Collection.html#optional-restrictions">optional</a>)
     * @throws NullPointerException if this list contains a null element and the
     *                              specified collection does not permit null elements
     *                              (<a href="Collection.html#optional-restrictions">optional</a>),
     *                              or if the specified collection is null
     * @see Collection#contains(Object)
     */
    public boolean removeAll(Collection<?> c) {
        return batchRemove(c, false, 0, size);
    }

    /**
     * Retains only the elements in this list that are contained in the
     * specified collection.  In other words, removes from this list all
     * of its elements that are not contained in the specified collection.
     * 仅保留 ArrayList 中指定集合中包含的元素。换句话说,从 ArrayList 中删除所有不包含在指定集合中的元素。
     * @param c collection containing elements to be retained in this list
     * @return {@code true} if this list changed as a result of the call
     * @throws ClassCastException   if the class of an element of this list
     *                              is incompatible with the specified collection
     *                              (<a href="Collection.html#optional-restrictions">optional</a>)
     * @throws NullPointerException if this list contains a null element and the
     *                              specified collection does not permit null elements
     *                              (<a href="Collection.html#optional-restrictions">optional</a>),
     *                              or if the specified collection is null
     * @see Collection#contains(Object)
     */
    public boolean retainAll(Collection<?> c) {
        return batchRemove(c, true, 0, size);
    }

    /**
     * 批处理移除
     * @param c 要移除的集合
     * @param complement 是否是补集
     *                   如果true:移除list中除了c集合中的所有元素
     *                   如果false:移除list中 c集合中的元素
     * @param from
     * @param end
     * @return
     */
    boolean batchRemove(Collection<?> c, boolean complement,
                        final int from, final int end) {
        // 检查要移除的集合不为空
        Objects.requireNonNull(c);
        final Object[] es = elementData;
        int r;
        // Optimize for initial run of survivors
        for (r = from; ; r++) {
            if (r == end)
                return false;
            if (c.contains(es[r]) != complement)
                break;
        }
        int w = r++;
        try {
            for (Object e; r < end; r++)
                if (c.contains(e = es[r]) == complement)
                    es[w++] = e;
        } catch (Throwable ex) {
            // Preserve behavioral compatibility with AbstractCollection,
            // even if c.contains() throws.
            System.arraycopy(es, r, es, w, end - r);
            w += end - r;
            throw ex;
        } finally {
            modCount += end - w;
            shiftTailOverGap(es, w, end);
        }
        return true;
    }

    /**
     * Saves the state of the {@code ArrayList} instance to a stream
     * (that is, serializes it).
     * 将 ArrayList 实例序列不啊
     * @param s the stream
     * @throws java.io.IOException if an I/O error occurs
     * @serialData The length of the array backing the {@code ArrayList}
     * instance is emitted (int), followed by all of its elements
     * (each an {@code Object}) in the proper order.
     */
    private void writeObject(java.io.ObjectOutputStream s)
            throws java.io.IOException {
        // Write out element count, and any hidden stuff
        // 写出元素计数以及任何隐藏的内容
        int expectedModCount = modCount;
        s.defaultWriteObject();

        // Write out size as capacity for behavioral compatibility with clone()
        // 写出大小作为与clone()行为兼容的容量
        s.writeInt(size);

        // Write out all elements in the proper order.
        // 按照正确的顺序写出所有元素。
        for (int i = 0; i < size; i++) {
            s.writeObject(elementData[i]);
        }

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

    /**
     * Reconstitutes the {@code ArrayList} instance from a stream (that is,
     * deserializes it).
     * 从反序列化中重构 ArrayList 实例
     * @param s the stream
     * @throws ClassNotFoundException if the class of a serialized object
     *                                could not be found
     * @throws java.io.IOException    if an I/O error occurs
     */
    private void readObject(java.io.ObjectInputStream s)
            throws java.io.IOException, ClassNotFoundException {

        // Read in size, and any hidden stuff
        // 阅读大小以及任何隐藏的内容
        s.defaultReadObject();

        // Read in capacity
        // 读入容量
        s.readInt(); // ignored

        if (size > 0) {
            // like clone(), allocate array based upon size not capacity
            // 像clone()一样,根据大小而不是容量分配数组
            SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Object[].class, size);
            Object[] elements = new Object[size];

            // Read in all elements in the proper order.
            // 按正确的顺序读入所有元素。
            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);
        }
    }

    /**
     * Returns a list iterator over the elements in this list (in proper
     * sequence), starting at the specified position in the list.
     * The specified index indicates the first element that would be
     * returned by an initial call to {@link ListIterator#next next}.
     * An initial call to {@link ListIterator#previous previous} would
     * return the element with the specified index minus one.
     *
     * <p>The returned list iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
     *
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public ListIterator<E> listIterator(int index) {
        rangeCheckForAdd(index);
        return new ListItr(index);
    }

    /**
     * Returns a list iterator over the elements in this list (in proper
     * sequence).
     *
     * <p>The returned list iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
     *
     * @see #listIterator(int)
     */
    public ListIterator<E> listIterator() {
        return new ListItr(0);
    }

    /**
     * Returns an iterator over the elements in this list in proper sequence.
     *
     * <p>The returned iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
     *
     * @return an iterator over the elements in this list in proper sequence
     */
    public Iterator<E> iterator() {
        return new Itr();
    }

    /**
     * An optimized version of AbstractList.Itr
     */
    private class Itr implements Iterator<E> {
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;

        // prevent creating a synthetic constructor
        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(elementAt(es, i));
                // update once at end to reduce heap write traffic
                cursor = i;
                lastRet = i - 1;
                checkForComodification();
            }
        }

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

    /**
     * An optimized version of AbstractList.ListItr
     */
    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();
            }
        }
    }

    /**
     * Returns a view of the portion of this list between the specified
     * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.  (If
     * {@code fromIndex} and {@code toIndex} are equal, the returned list is
     * empty.)  The returned list is backed by this list, so non-structural
     * changes in the returned list are reflected in this list, and vice-versa.
     * The returned list supports all of the optional list operations.
     *
     * <p>This method eliminates the need for explicit range operations (of
     * the sort that commonly exist for arrays).  Any operation that expects
     * a list can be used as a range operation by passing a subList view
     * instead of a whole list.  For example, the following idiom
     * removes a range of elements from a list:
     * <pre>
     *      list.subList(from, to).clear();
     * </pre>
     * Similar idioms may be constructed for {@link #indexOf(Object)} and
     * {@link #lastIndexOf(Object)}, and all of the algorithms in the
     * {@link Collections} class can be applied to a subList.
     *
     * <p>The semantics of the list returned by this method become undefined if
     * the backing list (i.e., this list) is <i>structurally modified</i> in
     * any way other than via the returned list.  (Structural modifications are
     * those that change the size of this list, or otherwise perturb it in such
     * a fashion that iterations in progress may yield incorrect results.)
     *
     * @throws IndexOutOfBoundsException {@inheritDoc}
     * @throws IllegalArgumentException  {@inheritDoc}
     */
    public List<E> subList(int fromIndex, int toIndex) {
        subListRangeCheck(fromIndex, toIndex, size);
        return new SubList<>(this, fromIndex, toIndex);
    }

    private static class SubList<E> extends AbstractList<E> implements RandomAccess {
        private final ArrayList<E> root;
        private final SubList<E> parent;
        private final int offset;
        private int size;

        /**
         * Constructs a sublist of an arbitrary ArrayList.
         */
        public SubList(ArrayList<E> root, int fromIndex, int toIndex) {
            this.root = root;
            this.parent = null;
            this.offset = fromIndex;
            this.size = toIndex - fromIndex;
            this.modCount = root.modCount;
        }

        /**
         * Constructs a sublist of another SubList.
         */
        private SubList(SubList<E> parent, 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) {
            Objects.checkIndex(index, size);
            checkForComodification();
            E oldValue = root.elementData(offset + index);
            root.elementData[offset + index] = element;
            return oldValue;
        }

        public E get(int index) {
            Objects.checkIndex(index, size);
            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) {
            Objects.checkIndex(index, size);
            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(this.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 void replaceAll(UnaryOperator<E> operator) {
            root.replaceAllRange(operator, offset, offset + size);
        }

        public boolean removeAll(Collection<?> c) {
            return batchRemove(c, false);
        }

        public boolean retainAll(Collection<?> c) {
            return batchRemove(c, true);
        }

        private boolean batchRemove(Collection<?> c, boolean complement) {
            checkForComodification();
            int oldSize = root.size;
            boolean modified =
                    root.batchRemove(c, complement, offset, offset + size);
            if (modified)
                updateSizeAndModCount(root.size - oldSize);
            return modified;
        }

        public boolean removeIf(Predicate<? super E> filter) {
            checkForComodification();
            int oldSize = root.size;
            boolean modified = root.removeIf(filter, offset, offset + size);
            if (modified)
                updateSizeAndModCount(root.size - oldSize);
            return modified;
        }

        public Object[] toArray() {
            checkForComodification();
            return Arrays.copyOfRange(root.elementData, offset, offset + size);
        }

        @SuppressWarnings("unchecked")
        public <T> T[] toArray(T[] a) {
            checkForComodification();
            if (a.length < size)
                return (T[]) Arrays.copyOfRange(
                        root.elementData, offset, offset + size, a.getClass());
            System.arraycopy(root.elementData, offset, a, 0, size);
            if (a.length > size)
                a[size] = null;
            return a;
        }

        public boolean equals(Object o) {
            if (o == this) {
                return true;
            }

            if (!(o instanceof List)) {
                return false;
            }

            boolean equal = root.equalsRange((List<?>) o, offset, offset + size);
            checkForComodification();
            return equal;
        }

        public int hashCode() {
            int hash = root.hashCodeRange(offset, offset + size);
            checkForComodification();
            return hash;
        }

        public int indexOf(Object o) {
            int index = root.indexOfRange(o, offset, offset + size);
            checkForComodification();
            return index >= 0 ? index - offset : -1;
        }

        public int lastIndexOf(Object o) {
            int index = root.lastIndexOfRange(o, offset, offset + size);
            checkForComodification();
            return index >= 0 ? index - offset : -1;
        }

        public boolean contains(Object o) {
            return indexOf(o) >= 0;
        }

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

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

            return new ListIterator<E>() {
                int cursor = index;
                int lastRet = -1;
                int expectedModCount = root.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();
                    Object[] elementData = root.elementData;
                    if (offset + i >= elementData.length)
                        throw new ConcurrentModificationException();
                    cursor = i + 1;
                    return (E) elementData[offset + (lastRet = i)];
                }

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

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

                public void forEachRemaining(Consumer<? super E> action) {
                    Objects.requireNonNull(action);
                    final int size = SubList.this.size;
                    int i = cursor;
                    if (i < size) {
                        final Object[] es = root.elementData;
                        if (offset + i >= es.length)
                            throw new ConcurrentModificationException();
                        for (; i < size && modCount == expectedModCount; i++)
                            action.accept(elementAt(es, offset + i));
                        // update once at end to reduce heap write traffic
                        cursor = i;
                        lastRet = i - 1;
                        checkForComodification();
                    }
                }

                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);
                        cursor = lastRet;
                        lastRet = -1;
                        expectedModCount = root.modCount;
                    } catch (IndexOutOfBoundsException ex) {
                        throw new ConcurrentModificationException();
                    }
                }

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

                    try {
                        root.set(offset + 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 = root.modCount;
                    } catch (IndexOutOfBoundsException ex) {
                        throw new ConcurrentModificationException();
                    }
                }

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

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

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

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

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

        private void updateSizeAndModCount(int sizeChange) {
            SubList<E> slist = this;
            do {
                slist.size += sizeChange;
                slist.modCount = root.modCount;
                slist = slist.parent;
            } while (slist != null);
        }

        public Spliterator<E> spliterator() {
            checkForComodification();

            // ArrayListSpliterator not used here due to late-binding
            return new Spliterator<E>() {
                private int index = offset; // current index, modified on advance/split
                private int fence = -1; // -1 until used; then one past last index
                private int expectedModCount; // initialized when fence set

                private int getFence() { // initialize fence to size on first use
                    int hi; // (a specialized variant appears in method forEach)
                    if ((hi = fence) < 0) {
                        expectedModCount = modCount;
                        hi = fence = offset + size;
                    }
                    return hi;
                }

                public ArrayList<E>.ArrayListSpliterator trySplit() {
                    int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
                    // ArrayListSpliterator can be used here as the source is already bound
                    return (lo >= mid) ? null : // divide range in half unless too small
                            root.new ArrayListSpliterator(lo, index = mid, expectedModCount);
                }

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

                public void forEachRemaining(Consumer<? super E> action) {
                    Objects.requireNonNull(action);
                    int i, hi, mc; // hoist accesses and checks from loop
                    ArrayList<E> lst = root;
                    Object[] a;
                    if ((a = lst.elementData) != null) {
                        if ((hi = fence) < 0) {
                            mc = modCount;
                            hi = offset + size;
                        } else
                            mc = expectedModCount;
                        if ((i = index) >= 0 && (index = hi) <= a.length) {
                            for (; i < hi; ++i) {
                                @SuppressWarnings("unchecked") E e = (E) a[i];
                                action.accept(e);
                            }
                            if (lst.modCount == mc)
                                return;
                        }
                    }
                    throw new ConcurrentModificationException();
                }

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

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

    /**
     * @throws NullPointerException {@inheritDoc}
     */
    @Override
    public void forEach(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        final int expectedModCount = modCount;
        final Object[] es = elementData;
        final int size = this.size;
        for (int i = 0; modCount == expectedModCount && i < size; i++)
            action.accept(elementAt(es, i));
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    }

    /**
     * Creates a <em><a href="Spliterator.html#binding">late-binding</a></em>
     * and <em>fail-fast</em> {@link Spliterator} over the elements in this
     * list.
     *
     * <p>The {@code Spliterator} reports {@link Spliterator#SIZED},
     * {@link Spliterator#SUBSIZED}, and {@link Spliterator#ORDERED}.
     * Overriding implementations should document the reporting of additional
     * characteristic values.
     *
     * @return a {@code Spliterator} over the elements in this list
     * @since 1.8
     */
    @Override
    public Spliterator<E> spliterator() {
        return new ArrayListSpliterator(0, -1, 0);
    }

    /**
     * Index-based split-by-two, lazily initialized Spliterator
     */
    final class ArrayListSpliterator implements Spliterator<E> {

        /*
         * If ArrayLists were immutable, or structurally immutable (no
         * adds, removes, etc), we could implement their spliterators
         * with Arrays.spliterator. Instead we detect as much
         * interference during traversal as practical without
         * sacrificing much performance. We rely primarily on
         * modCounts. These are not guaranteed to detect concurrency
         * violations, and are sometimes overly conservative about
         * within-thread interference, but detect enough problems to
         * be worthwhile in practice. To carry this out, we (1) lazily
         * initialize fence and expectedModCount until the latest
         * point that we need to commit to the state we are checking
         * against; thus improving precision.  (This doesn't apply to
         * SubLists, that create spliterators with current non-lazy
         * values).  (2) We perform only a single
         * ConcurrentModificationException check at the end of forEach
         * (the most performance-sensitive method). When using forEach
         * (as opposed to iterators), we can normally only detect
         * interference after actions, not before. Further
         * CME-triggering checks apply to all other possible
         * violations of assumptions for example null or too-small
         * elementData array given its size(), that could only have
         * occurred due to interference.  This allows the inner loop
         * of forEach to run without any further checks, and
         * simplifies lambda-resolution. While this does entail a
         * number of checks, note that in the common case of
         * list.stream().forEach(a), no checks or other computation
         * occur anywhere other than inside forEach itself.  The other
         * less-often-used methods cannot take advantage of most of
         * these streamlinings.
         */

        private int index; // current index, modified on advance/split
        private int fence; // -1 until used; then one past last index
        private int expectedModCount; // initialized when fence set

        /**
         * Creates new spliterator covering the given range.
         */
        ArrayListSpliterator(int origin, int fence, int expectedModCount) {
            this.index = origin;
            this.fence = fence;
            this.expectedModCount = expectedModCount;
        }

        private int getFence() { // initialize fence to size on first use
            int hi; // (a specialized variant appears in method forEach)
            if ((hi = fence) < 0) {
                expectedModCount = modCount;
                hi = fence = size;
            }
            return hi;
        }

        public ArrayListSpliterator trySplit() {
            int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
            return (lo >= mid) ? null : // divide range in half unless too small
                    new ArrayListSpliterator(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) elementData[i];
                action.accept(e);
                if (modCount != expectedModCount)
                    throw new ConcurrentModificationException();
                return true;
            }
            return false;
        }

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

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

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

    // A tiny bit set implementation

    private static long[] nBits(int n) {
        return new long[((n - 1) >> 6) + 1];
    }

    private static void setBit(long[] bits, int i) {
        bits[i >> 6] |= 1L << i;
    }

    private static boolean isClear(long[] bits, int i) {
        return (bits[i >> 6] & (1L << i)) == 0;
    }

    /**
     * @throws NullPointerException {@inheritDoc}
     */
    @Override
    public boolean removeIf(Predicate<? super E> filter) {
        return removeIf(filter, 0, size);
    }

    /**
     * Removes all elements satisfying the given predicate, from index
     * i (inclusive) to index end (exclusive).
     */
    boolean removeIf(Predicate<? super E> filter, int i, final int end) {
        Objects.requireNonNull(filter);
        int expectedModCount = modCount;
        final Object[] es = elementData;
        // Optimize for initial run of survivors
        for (; i < end && !filter.test(elementAt(es, i)); i++)
            ;
        // Tolerate predicates that reentrantly access the collection for
        // read (but writers still get CME), so traverse once to find
        // elements to delete, a second pass to physically expunge.
        if (i < end) {
            final int beg = i;
            final long[] deathRow = nBits(end - beg);
            deathRow[0] = 1L;   // set bit 0
            for (i = beg + 1; i < end; i++)
                if (filter.test(elementAt(es, i)))
                    setBit(deathRow, i - beg);
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            modCount++;
            int w = beg;
            for (i = beg; i < end; i++)
                if (isClear(deathRow, i - beg))
                    es[w++] = es[i];
            shiftTailOverGap(es, w, end);
            return true;
        } else {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            return false;
        }
    }

    @Override
    public void replaceAll(UnaryOperator<E> operator) {
        replaceAllRange(operator, 0, size);
        modCount++;
    }

    private void replaceAllRange(UnaryOperator<E> operator, int i, int end) {
        Objects.requireNonNull(operator);
        final int expectedModCount = modCount;
        final Object[] es = elementData;
        for (; modCount == expectedModCount && i < end; i++)
            es[i] = operator.apply(elementAt(es, i));
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    }

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

    void checkInvariants() {
        // assert size >= 0;
        // assert size == elementData.length || elementData[size] == null;
    }
}

2.6 如何在阅读 ArrayList 源码时添加注释
  1. 创建一个 ArrayList 类;
  2. 将代码拷贝进来,同时创建一个 AbstractList 抽象类,也将代码拷贝进去;
  3. 剩下的就是导一些包就行了。

三、ArrayList 相关知识

3.1 ArrayList 的 fail-fast

modCount 用来记录 ArrayList 结构发生变化的次数。

结构发生变化是指添加或删除至少一个元素的所有操作,仅设置元素的值不算结构发生变化。

在进行序列化或者迭代等操作时,需要比较操作前后 modCount 是否改变,如果改变了需要抛出

3.2 list 的遍历方式选择
  • 实现了 RandomAccess 接口的 list,优先选择普通 for 循环,其次 foreach
  • 未实现了 RandomAccess 接口的 list,优先选择 iterator 遍历,大 size 的数据,千万不要使用普通 for 循环
3.3 ArrayList 和 Vector 比较
  • Vector 是同步的,因此开销比 ArrayList 大,访问速度更慢。最好使用 ArrayList 而不是 Vector,因为同步操作完全可以由程序员自己来控制;
  • Vector 每次扩容请求其大小的 2 倍空间,而 ArrayList 是 1.5 倍。
3.4 为啥线程不安全还是用 ArrayList

因为在正常使用的场景中,都是用来查询,不会涉及太频繁的增删。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值