基于JDK1.8 的ArrayList源码分析

2023-11-16

基于JDK1.8 的ArrayList源码分析,代码注释。

JDK版本:jdk1.8.0_181

package java.util;

import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import sun.misc.SharedSecrets;

/**
 * Resizable-array implementation of the <tt>List</tt> interface.  Implements
 * all optional list operations, and permits all elements, including
 * <tt>null</tt>.  In addition to implementing the <tt>List</tt> 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
 * <tt>Vector</tt>, except that it is unsynchronized.)
 *
 * <p>The <tt>size</tt>, <tt>isEmpty</tt>, <tt>get</tt>, <tt>set</tt>,
 * <tt>iterator</tt>, and <tt>listIterator</tt> operations run in constant
 * time.  The <tt>add</tt> 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 <tt>LinkedList</tt> implementation.
 *
 * <p>Each <tt>ArrayList</tt> 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 <tt>ArrayList</tt> instance
 * before adding a large number of elements using the <tt>ensureCapacity</tt>
 * operation.  This may reduce the amount of incremental reallocation.
 *
 * <p><strong>Note that this implementation is not synchronized.</strong>
 * If multiple threads access an <tt>ArrayList</tt> 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.
 *
 * 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><a name="fail-fast">
 * The iterators returned by this class's {@link #iterator() iterator} and
 * {@link #listIterator(int) listIterator} methods are <em>fail-fast</em>:</a>
 * 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}/../technotes/guides/collections/index.html">
 * Java Collections Framework</a>.
 *
 * @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.
     * 默认初始容量大小为10。
     */
    private static final int DEFAULT_CAPACITY = 10;

    /**
     * Shared empty array instance used for empty instances.
     * 共享空数组实例,用于创建空的ArrayList实例。
     */
    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.
     *
     * 共享空数组实例,用于默认大小的空实例。
     * 我们将其与“EMPTY_ELEMENTDATA”区分开来,以便知道在添加第一个元素时数组需要扩容多大。
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    /**
     * 存储ArrayList元素的数组。
     * 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的容量是这个数组缓冲区的长度。
     * 当第一个元素被添加时,空的ArrayList(元素数据elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA时)大小,
     * 将被扩容为DEFAULT_CAPACITY大小,ArrayList大小将被扩容为10。
     */
    transient Object[] elementData; // non-private to simplify nested class access

    /**
     * The size of the ArrayList (the number of elements it contains).
     * ArrayList的大小(包含元素的数量)
     * @serial
     */
    private int size;

    /**
     * Constructs an empty list with the specified initial capacity.
     * 根据指定的初始容量initialCapacity大小,创建空的ArrayList。
     * @param  initialCapacity  the initial capacity of the list    指定初始容量大小参数,ArrayList列表的初始容量大小。
     * @throws IllegalArgumentException if the specified initial capacity
     *         is negative  如果指定的初始容量大小为负数,抛出IllegalArgumentException异常。
     */
    public ArrayList(int initialCapacity) {
        //初始容量大于0。
        if (initialCapacity > 0) {
            //创建初始容量大小的数组。
            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.
     * 构造一个空的ArrayList,第1个元素添加时,ArrayList容量大小将变为10。
     */
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    /**
     * 根据指定的集合参数c,创建ArrayList列表。
     * Constructs a list containing the elements of the specified
     * collection, in the order they are returned by the collection's
     * iterator.
     * 构造包含指定集合元素的列表,按照集合迭代器返回的顺序。
     * @param c the collection whose elements are to be placed into this list
     *          要将其元素放入该列表的集合,指定集合的参数c。
     * @throws NullPointerException if the specified collection is null
     *          如果指定的集合为空,抛出异常。
     */
    public ArrayList(Collection<? extends E> c) {
        //将指定集合元素的参数c赋值elementData
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            //c.toArray可能(不正确地)不返回Object[](参见JDK 6260652编号bug)
            // 《JDK1.6集合框架bug》 https://blog.csdn.net/aitangyong/article/details/30274749
            //比较object的运行时类,字节码文件。
            if (elementData.getClass() != Object[].class)
                //用来创建1个Object[]数组,这样数组中就可以存放任意对象了。
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            // 指定集合元素的参数c大小为0,创建空的ArrayList。
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

    /**
     * 调整ArrayList的容量大小。将此ArrayList实例的容量修剪为列表的当前大小。
     * Trims the capacity of this <tt>ArrayList</tt> instance to be the
     * list's current size.  An application can use this operation to minimize
     * the storage of an <tt>ArrayList</tt> instance.
     *
     * 将ArrayList实例的容量调整为列表的当前大小。
     * 应用程序可以使用该操作来最小化ArrayList实例的存储空间。
     */
    public void trimToSize() {
        //TODO modCount
        modCount++;
        if (size < elementData.length) {
            elementData = (size == 0)
              ? EMPTY_ELEMENTDATA
              : Arrays.copyOf(elementData, size);
        }
    }

    /**
     * 确保最小容量。
     * 在add大量元素之前使用ensureCapacity方法,以减少增量重新分配内存的次数。
     * Increases the capacity of this <tt>ArrayList</tt> instance, if
     * necessary, to ensure that it can hold at least the number of elements
     * specified by the minimum capacity argument.
     * 增加ArrayList实例的容量,如果有必要,确保它至少可以容纳最小容量参数minCapacity指定的元素数量。
     * @param   minCapacity   the desired minimum capacity 所需的最小容量。
     */
    public void ensureCapacity(int minCapacity) {
        int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
            // any size if not default element table  如果数组大小不是默认的空元素列表。
            ? 0
            // larger than default for default empty table. It's already
            // supposed to be at default size.
            : DEFAULT_CAPACITY;

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

    /**
     * 计算需要扩容的容量大小,得到最小扩容量。
     * @param elementData elementData存储ArrayList元素的数组。
     * @param minCapacity 最小扩容量。
     * @return
     */
    private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            //指定扩容大小参数minCapacity与默认为10的DEFAULT_CAPACITY中,取一个最大值。
            //当要add进第1个元素时,minCapacity为1,在Math.max()方法比较后,minCapacity为10。
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }

    //确保内部容量大小。
    private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }

    //判断是否需要扩容。
    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code 考虑了溢出情况的代码
        //《overflow-conscious code》 https://blog.csdn.net/lijianqingfeng/article/details/107912190
        //存储ArrayList元素的数组
        if (minCapacity - elementData.length > 0)
            //调用grow方法进行扩容。
            grow(minCapacity);
    }

    /**
     * 要分配的数组的最大大小。
     * The maximum size of array to allocate.
     * Some VMs reserve some header words in an array.
     * Attempts to allocate larger arrays may result in
     * OutOfMemoryError: Requested array size exceeds VM limit
     * 要分配的数组的最大大小。
     * 有些虚拟机在数组中预留保存一些header头部数据。(所以int最大值减8,8位用来保存header头部数据)
     * 尝试分配更大的数组可能会导致OutOfMemoryError内存错误:请求的数组大小超过虚拟机限制。
     */
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    /**
     * ArrayList扩容的方法。
     * Increases the capacity to ensure that it can hold at least the
     * number of elements specified by the minimum capacity argument.
     * 增加数组容量,以确保它至少可以容纳最小容量参数minCapacity指定的元素数量。
     * @param minCapacity the desired minimum capacity  所需的最小容量。
     */
    private void grow(int minCapacity) {
        // overflow-conscious code
        //获取到旧容量,oldCapacity为旧容量。
        int oldCapacity = elementData.length;
        //相当于int newCapacity = oldCapacity + (oldCapacity / 2),也就是newCapacity = oldCapacity * (1.5)。
        //将oldCapacity右移一位,其效果相当于oldCapacity/2。
        //位运算的速度快于整除运算,将新容量更新为旧容量的1.5倍,扩容50%。
        //ArrayList每次扩容之后容量都会变为原来的1.5倍左右。
        //newCapacity为新容量。
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        //检查新容量是否大于最小需要容量。
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        //检查新容量是否大于MAX_ARRAY_SIZE。
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

    //极大的容量,最大容量为Integer.MAX_VALUE。
    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  返回此ArrayList列表中的元素个数。
     */
    public int size() {
        return size;
    }

    /**
     * Returns <tt>true</tt> if this list contains no elements.
     * 如果ArrayList列表不包含元素,则返回true。
     * @return <tt>true</tt> if this list contains no elements  如果ArrayList列表不包含元素,则返回true。
     */
    public boolean isEmpty() {
        return size == 0;
    }

    /**
     * Returns <tt>true</tt> if this list contains the specified element.
     * More formally, returns <tt>true</tt> if and only if this list contains
     * at least one element <tt>e</tt> such that
     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
     *
     * 如果该列表包含指定的元素,则返回true。
     * 更正式的说法是,当且仅当该列表包含至少一个元素e且<tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>时,返回true。
     * @param o element whose presence in this list is to be tested 验证o元素在列表中是否存在。
     * @return <tt>true</tt> if this list contains the specified element    如果此列表包含指定的元素返回true。
     */
    public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }

    /**
     * 返回此列表中第一次出现的指定元素的索引,如果此列表不包含该元素,则返回-1。
     *
     * 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 <tt>i</tt> such that
     * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
     * or -1 if there is no such index.
     *
     * 返回列表中指定元素的第一个匹配项的索引,如果列表中不包含该元素,返回-1。
     * 更确切说,返回匹配元素的最小的索引i,(o==null ? get(i)==null : o.equals(get(i)))
     * 如果没有这样的下标,则返回-1。
     */
    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;
    }

    /**
     * 返回此列表中指定元素最后一次出现的索引,如果此列表不包含该元素,则返回-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 <tt>i</tt> such that
     * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
     * or -1 if there is no such index.
     *
     * 返回指定元素在列表中的最后一个匹配项的索引,如果列表中不包含该元素,则返回-1。
     * 更确切地说,返回匹配元素的最高的索引i,(o==null ? get(i)==null o.equals(get(i)))
     * 如果没有这样的下标,则返回-1。
     */
    public int lastIndexOf(Object o) {
        if (o == null) {
            for (int i = size-1; i >= 0; i--)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = size-1; i >= 0; i--)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

    /**
     * Returns a shallow copy of this <tt>ArrayList</tt> instance.  (The
     * elements themselves are not copied.)
     *
     * 返回此数组列表实例的浅拷贝。(元素本身不会被复制。)
     *
     * @return a clone of this <tt>ArrayList</tt> instance  返回这个ArrayList实例的克隆。
     */
    public Object clone() {
        try {
            ArrayList<?> v = (ArrayList<?>) super.clone();
            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.
     * 此方法充当了基于array数组和基于collection集合的api之间的桥梁。
     *
     * @return an array containing all of the elements in this list in
     *         proper sequence
     *         以适当的顺序包含列表中所有元素的数组。
     */
    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
     * <tt>null</tt>.  (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.)
     *
     * @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.
     * @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
     * @throws NullPointerException if the specified array is null
     */
    @SuppressWarnings("unchecked")
    public <T> T[] toArray(T[] a) {
        if (a.length < size)
            // Make a new array of a's runtime type, but my contents:
            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];
    }

    /**
     * Returns the element at the specified position in this list.
     * 返回列表中指定位置的元素。
     *
     * @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) {
        rangeCheck(index);

        return elementData(index);
    }

    /**
     * 替换指定位置的元素。
     * Replaces the element at the specified position in this list with
     * the specified element.
     * 将此列表中指定位置的元素替换为指定的元素。
     *
     * @param index index of the element to replace  Index是要替换的元素的索引。
     * @param element element to be stored at the specified position  element元素被存储在指定的位置。
     * @return the element previously at the specified position  返回先前位于指定位置的旧元素。
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public E set(int index, E element) {
        rangeCheck(index);

        E oldValue = elementData(index);
        elementData[index] = element;
        return oldValue;
    }

    /**
     * 将指定的元素追加到list列表的末尾。
     * Appends the specified element to the end of this list.
     * 将指定的元素追加到此ArrayList列表的末尾。
     *
     * @param e element to be appended to this list 元素添加到此列表。
     * @return <tt>true</tt> (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
        //
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        //通过为数组赋值的方式为ArrayList列表添加元素。
        elementData[size++] = e;
        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).
     * 将指定的元素插入到此列表中的指定位置。
     * 将当前位置的元素(如果有的话)和随后的元素向右移动(索引下标增加1)。
     *
     * @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);

        ensureCapacityInternal(size + 1);  // Increments modCount!!
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        elementData[index] = element;
        size++;
    }

    /**
     * 根据索引位置移除元素。
     * Removes the element at the specified position in this list.
     * Shifts any subsequent elements to the left (subtracts one from their
     * indices).
     * 移除列表中指定索引位置的元素。
     * 将后面的所有元素向左移动(索引下标减去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) {
        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; // clear to let GC do its work  清除让GC工作。

        return oldValue;
    }

    /**
     * 删除指定元素的第一个匹配项。
     * 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
     * <tt>i</tt> such that
     * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>
     * (if such an element exists).  Returns <tt>true</tt> if this list
     * contained the specified element (or equivalently, if this list
     * changed as a result of the call).
     *
     * 如果指定的元素存在列表中,从该列表中删除指定元素的第一个匹配项。
     * 如果列表中不包含指定的元素,则列表元素不变化。
     * 更确切的讲,如果存在匹配的元素,删除索引最小的匹配项元素, (o==null ? get(i)==null : o.equals(get(i))) 。
     * 如果该列表包含指定的元素,则返回true(或者,如果该列表因调用而发生更改,则返回true)。
     *
     * @param o element to be removed from this list, if present    如果存在o元素,从列表中删除。
     * @return <tt>true</tt> if this list contained the specified element   如果此列表包含指定的元素o,返回true。
     */
    public boolean remove(Object o) {
        if (o == null) {
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
        } else {
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }

    /*
     * 快速删除第index个元素。
     * Private remove method that skips bounds checking and does not
     * return the value removed.
     * 跳过边界检查且不返回已删除值的私有remove方法。
     */
    private void fastRemove(int index) {
        modCount++;
        //计算出需要向左移动多少位。
        int numMoved = size - index - 1;
        //从index+1开始,用后面的元素替换前面的元素。
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        //将最后一个元素设为null。
        elementData[--size] = null; // clear to let GC do its work
    }

    /**
     * 清空ArrayList,将全部的元素设为null。
     * Removes all of the elements from this list.  The list will
     * be empty after this call returns.
     *
     * 从ArrayList列表中移除所有元素。
     * 在调用此方法返回之后,ArrayList列表将变为空。
     */
    public void clear() {
        modCount++;

        // clear to let GC do its work
        for (int i = 0; i < size; i++)
            elementData[i] = null;

        size = 0;
    }

    /**
     * 将指定集合中的元素追加到列表的末尾。
     * 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.)
     *
     * 将指定集合中的所有元素追加到此列表的末尾,按照指定集合的迭代器返回的顺序。
     * 如果在操作进行时修改了指定的集合,则此操作的行为是未定义的。
     * (这意味着如果指定的集合是这个列表,并且这个列表是非空的,那么这个调用的行为是未定义的。)
     *
     * @param c collection containing elements to be added to this list 包含要添加到此列表中的C元素集合
     * @return <tt>true</tt> if this list changed as a result of the call   如果该列表因调用而改变,返回true。
     * @throws NullPointerException if the specified collection is null 如果指定的集合为空,抛出NullPointerException异常。
     */
    public boolean addAll(Collection<? extends E> c) {
        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);  // Increments modCount
        System.arraycopy(a, 0, elementData, size, numNew);
        size += numNew;
        return numNew != 0;
    }

    /**
     * 从指定位置开始将指定集合中的所有元素插入list列表。
     *
     * 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.
     *
     * @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 <tt>true</tt> if this list changed as a result of the call
     * @throws IndexOutOfBoundsException {@inheritDoc}
     * @throws NullPointerException if the specified collection is null
     */
    public boolean addAll(int index, Collection<? extends E> c) {
        rangeCheckForAdd(index);

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

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

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

    /**
     * 从list列表中删除索引在fromIndex(包含)和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.)
     *
     * @throws IndexOutOfBoundsException if {@code fromIndex} or
     *         {@code toIndex} is out of range
     *         ({@code fromIndex < 0 ||
     *          fromIndex >= size() ||
     *          toIndex > size() ||
     *          toIndex < fromIndex})
     */
    protected void removeRange(int fromIndex, int toIndex) {
        modCount++;
        //要复制的数组元素的数量。把后面的元素移动到前面。
        int numMoved = size - toIndex;
        System.arraycopy(elementData, toIndex, elementData, fromIndex,
                         numMoved);

        // clear to let GC do its work
        int newSize = size - (toIndex-fromIndex);
        for (int i = newSize; i < size; i++) {
            elementData[i] = null;
        }
        size = newSize;
    }

    /**
     * 检查索引界限。
     * Checks if the given index is in range.  If not, throws an appropriate
     * runtime exception.  This method does *not* check if the index is
     * negative: It is always used immediately prior to an array access,
     * which throws an ArrayIndexOutOfBoundsException if index is negative.
     *
     * 检查给定的索引是否在范围内。如果索引不在范围内,则抛出的运行时异常。
     * 这个方法不会检查索引是否为负数:总是在访问数组之前使用。
     * 如果index为负数,则抛出ArrayIndexOutOfBoundsException异常。
     */
    private void rangeCheck(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    /**
     * 检查索引界限。
     * A version of rangeCheck used by add and addAll.
     * 用于add和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;
    }

    /**
     * 删除指定Collection集合中包含的所有元素。
     *
     * Removes from this list all of its elements that are contained in the
     * specified collection.
     *
     * @param c collection containing elements to be removed from 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 removeAll(Collection<?> c) {
        Objects.requireNonNull(c);
        return batchRemove(c, false);
    }

    /**
     * 用于仅保留此list列表中包含在指定Collection集合中的元素。
     * 换句话说,从此list列表中删除未包含在指定Collection集合中的所有元素。
     *
     * 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.
     *
     * @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) {
        Objects.requireNonNull(c);
        return batchRemove(c, true);
    }

    private boolean batchRemove(Collection<?> c, boolean complement) {
        final Object[] elementData = this.elementData;
        int r = 0, w = 0;
        boolean modified = false;
        try {
            for (; r < size; r++)
                if (c.contains(elementData[r]) == complement)
                    elementData[w++] = elementData[r];
        } finally {
            // Preserve behavioral compatibility with AbstractCollection,
            // even if c.contains() throws.
            if (r != size) {
                System.arraycopy(elementData, r,
                                 elementData, w,
                                 size - r);
                w += size - r;
            }
            if (w != size) {
                // clear to let GC do its work
                for (int i = w; i < size; i++)
                    elementData[i] = null;
                modCount += size - w;
                size = w;
                modified = true;
            }
        }
        return modified;
    }

    /**
     * Save the state of the <tt>ArrayList</tt> instance to a stream (that
     * is, serialize it).
     *
     * @serialData The length of the array backing the <tt>ArrayList</tt>
     *             instance is emitted (int), followed by all of its elements
     *             (each an <tt>Object</tt>) 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 behavioural compatibility with 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();
        }
    }

    /**
     * Reconstitute the <tt>ArrayList</tt> instance from a stream (that is,
     * deserialize it).
     */
    private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
        elementData = EMPTY_ELEMENTDATA;

        // Read in size, and any hidden stuff
        s.defaultReadObject();

        // Read in capacity
        s.readInt(); // ignored

        if (size > 0) {
            // be like clone(), allocate array based upon size not capacity
            int capacity = calculateCapacity(elementData, size);
            SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, capacity);
            ensureCapacityInternal(size);

            Object[] a = elementData;
            // Read in all elements in the proper order.
            for (int i=0; i<size; i++) {
                a[i] = s.readObject();
            }
        }
    }

    /**
     * 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) {
        if (index < 0 || index > size)
            throw new IndexOutOfBoundsException("Index: "+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;

        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
        @SuppressWarnings("unchecked")
        public void forEachRemaining(Consumer<? super E> consumer) {
            Objects.requireNonNull(consumer);
            final int size = ArrayList.this.size;
            int i = cursor;
            if (i >= size) {
                return;
            }
            final Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length) {
                throw new ConcurrentModificationException();
            }
            while (i != size && modCount == expectedModCount) {
                consumer.accept((E) elementData[i++]);
            }
            // update once at end of iteration 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, 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 + ")");
    }

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

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

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

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

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

        public void add(int index, E e) {
            rangeCheckForAdd(index);
            checkForComodification();
            parent.add(parentOffset + index, e);
            this.modCount = parent.modCount;
            this.size++;
        }

        public E remove(int index) {
            rangeCheck(index);
            checkForComodification();
            E result = parent.remove(parentOffset + index);
            this.modCount = parent.modCount;
            this.size--;
            return result;
        }

        protected void removeRange(int fromIndex, int toIndex) {
            checkForComodification();
            parent.removeRange(parentOffset + fromIndex,
                               parentOffset + toIndex);
            this.modCount = parent.modCount;
            this.size -= toIndex - fromIndex;
        }

        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();
            parent.addAll(parentOffset + index, c);
            this.modCount = parent.modCount;
            this.size += 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 = ArrayList.this.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 = ArrayList.this.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 = ArrayList.this.elementData;
                    if (offset + i >= elementData.length)
                        throw new ConcurrentModificationException();
                    cursor = i;
                    return (E) elementData[offset + (lastRet = i)];
                }

                @SuppressWarnings("unchecked")
                public void forEachRemaining(Consumer<? super E> consumer) {
                    Objects.requireNonNull(consumer);
                    final int size = SubList.this.size;
                    int i = cursor;
                    if (i >= size) {
                        return;
                    }
                    final Object[] elementData = ArrayList.this.elementData;
                    if (offset + i >= elementData.length) {
                        throw new ConcurrentModificationException();
                    }
                    while (i != size && modCount == expectedModCount) {
                        consumer.accept((E) elementData[offset + (i++)]);
                    }
                    // update once at end of iteration to reduce heap write traffic
                    lastRet = cursor = i;
                    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 = ArrayList.this.modCount;
                    } catch (IndexOutOfBoundsException ex) {
                        throw new ConcurrentModificationException();
                    }
                }

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

                    try {
                        ArrayList.this.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 = ArrayList.this.modCount;
                    } catch (IndexOutOfBoundsException ex) {
                        throw new ConcurrentModificationException();
                    }
                }

                final void checkForComodification() {
                    if (expectedModCount != ArrayList.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 >= this.size)
                throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
        }

        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 (ArrayList.this.modCount != this.modCount)
                throw new ConcurrentModificationException();
        }

        public Spliterator<E> spliterator() {
            checkForComodification();
            return new ArrayListSpliterator<E>(ArrayList.this, offset,
                                               offset + this.size, this.modCount);
        }
    }

    @Override
    public void forEach(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        final int expectedModCount = modCount;
        @SuppressWarnings("unchecked")
        final E[] elementData = (E[]) this.elementData;
        final int size = this.size;
        for (int i=0; modCount == expectedModCount && i < size; i++) {
            action.accept(elementData[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<>(this, 0, -1, 0);
    }

    /** Index-based split-by-two, lazily initialized Spliterator */
    static final class ArrayListSpliterator<E> 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 final ArrayList<E> list;
        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

        /** Create new spliterator covering the given  range */
        ArrayListSpliterator(ArrayList<E> list, int origin, int fence,
                             int expectedModCount) {
            this.list = list; // OK if null unless traversed
            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)
            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 : // divide range in half unless too small
                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; // hoist accesses and checks from loop
            ArrayList<E> lst; Object[] a;
            if (action == null)
                throw new NullPointerException();
            if ((lst = list) != null && (a = lst.elementData) != null) {
                if ((hi = fence) < 0) {
                    mc = lst.modCount;
                    hi = lst.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 (long) (getFence() - index);
        }

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

    @Override
    public boolean removeIf(Predicate<? super E> filter) {
        Objects.requireNonNull(filter);
        // figure out which elements are to be removed
        // any exception thrown from the filter predicate at this stage
        // will leave the collection unmodified
        int removeCount = 0;
        final BitSet removeSet = new BitSet(size);
        final int expectedModCount = modCount;
        final int size = this.size;
        for (int i=0; modCount == expectedModCount && i < size; i++) {
            @SuppressWarnings("unchecked")
            final E element = (E) elementData[i];
            if (filter.test(element)) {
                removeSet.set(i);
                removeCount++;
            }
        }
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }

        // shift surviving elements left over the spaces left by removed elements
        final boolean anyToRemove = removeCount > 0;
        if (anyToRemove) {
            final int newSize = size - removeCount;
            for (int i=0, j=0; (i < size) && (j < newSize); i++, j++) {
                i = removeSet.nextClearBit(i);
                elementData[j] = elementData[i];
            }
            for (int k=newSize; k < size; k++) {
                elementData[k] = null;  // Let gc do its work
            }
            this.size = newSize;
            if (modCount != expectedModCount) {
                throw new ConcurrentModificationException();
            }
            modCount++;
        }

        return anyToRemove;
    }

    @Override
    @SuppressWarnings("unchecked")
    public void replaceAll(UnaryOperator<E> operator) {
        Objects.requireNonNull(operator);
        final int expectedModCount = modCount;
        final int size = this.size;
        for (int i=0; modCount == expectedModCount && i < size; i++) {
            elementData[i] = operator.apply((E) elementData[i]);
        }
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        modCount++;
    }

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于JDK1.8 的ArrayList源码分析 的相关文章

  • ElasticBeanstalk Java,Spring 活动配置文件

    我正在尝试通过 AWS ElasticBeanstalk 启动 spring boot jar 一切正常 配置文件为 默认 有谁知道如何为 java ElasticBeanstalk 应用程序 不是 tomcat 设置活动配置文件 spri
  • AES 加密 Java/plsql

    我需要在Java和plsql DBMS CRYPTO for Oracle 10g 上实现相同的加密 解密应用程序 两种实现都工作正常 但这里的问题是我对相同纯文本的加密得到了不同的输出 下面是用于加密 解密过程的代码 Java 和 PLS
  • 如何测试 JUnit 测试的 Comparator?

    我需要测试 Compare 方法 但我对如何测试感到困惑 我可以看看该怎么做吗 public class MemberComparator implements Comparator
  • 在数据流模板中调用 waitUntilFinish() 后可以运行代码吗?

    我有一个批处理 Apache Beam 作业 它从 GCS 获取文件作为输入 我的目标是根据执行后管道的状态将文件移动到两个 GCS 存储桶之一 如果管道执行成功 则将文件移动到存储桶 A 否则 如果管道在执行过程中出现任何未处理的异常 则
  • Java 页面爬行和解析之 Crawler4j 与 Jsoup

    我想获取页面的内容并提取其中的特定部分 据我所知 此类任务至少有两种解决方案 爬虫4j https github com yasserg crawler4j and Jsoup http jsoup org 它们都能够检索页面的内容并提取其
  • jdbc4.MySQLSyntaxErrorException:数据库中不存在表

    我正在使用 SpringBoot 开发一个网络应用程序 这是我的application properties文件来指定访问数据库的凭据 spring datasource driverClassName com mysql jdbc Dri
  • Prim 的迷宫生成算法:获取相邻单元格

    我基于 Prim 算法编写了一个迷宫生成器程序 该算法是 Prim 算法的随机版本 从充满墙壁的网格开始 选择一个单元格 将其标记为迷宫的一部分 将单元格的墙壁添加到墙壁列表中 While there are walls in the li
  • 请求位置更新参数

    这就是 requestLocationUpdates 的样子 我使用它的方式 requestLocationUpdates String provider long minTime float minDistance LocationLis
  • Java中接口作为方法参数

    前几天去面试 被问到了这样的问题 问 反转链表 给出以下代码 public class ReverseList interface NodeList int getItem NodeList nextNode void reverse No
  • 反思 Groovy 脚本中声明的函数

    有没有一种方法可以获取 Groovy 脚本中声明的函数的反射数据 该脚本已通过GroovyShell目的 具体来说 我想枚举脚本中的函数并访问附加到它们的注释 Put this到 Groovy 脚本的最后一行 它将作为脚本的返回值 a la
  • 如何在 JFreeChart TimeSeries 图表上显示降雨指数和温度?

    目前 我的 TimeSeries 图表每 2 秒显示一个位置的温度 现在 如果我想每2秒显示一次降雨指数和温度 我该如何实现呢 这是我的代码 import testWeatherService TestWeatherTimeLapseSer
  • 使用 AWS Java SDK 为现有 S3 对象设置 Expires 标头

    我正在更新 Amazon S3 存储桶中的现有对象以设置一些元数据 我想设置 HTTPExpires每个对象的标头以更好地处理 HTTP 1 0 客户端 我们正在使用AWS Java SDK http aws amazon com sdkf
  • Java直接内存:在自定义类中使用sun.misc.Cleaner

    在 Java 中 NIO 直接缓冲区分配的内存通过以下方式释放 sun misc Cleaner实例 一些比对象终结更有效的特殊幻像引用 这种清洁器机制是否仅针对直接缓冲区子类硬编码在 JVM 中 或者是否也可以在自定义组件中使用清洁器 例
  • 将多模块 Maven 项目导入 Eclipse 时出现问题 (STS 2.5.2)

    我刚刚花了最后一个小时查看 Stackoverflow com 上的线程 尝试将 Maven 项目导入到 Spring ToolSuite 2 5 2 中 Maven 项目有多个模块 当我使用 STS 中的 Import 向导导入项目时 所
  • Java中未绑定通配符泛型的用途和要点是什么?

    我不明白未绑定通配符泛型有什么用 具有上限的绑定通配符泛型 stuff for Object item stuff System out println item Since PrintStream println 可以处理所有引用类型 通
  • 如何在 Maven 中显示消息

    如何在 Maven 中显示消息 在ant中 我们确实有 echo 来显示消息 但是在maven中 我该怎么做呢 您可以使用 antrun 插件
  • 运行 Jar 文件时出现问题

    我已将 java 项目编译成 Jar 文件 但运行它时遇到问题 当我跑步时 java jar myJar jar 我收到以下错误 Could not find the main class myClass 类文件不在 jar 的根目录中 因
  • Java - 不要用 bufferedwriter 覆盖

    我有一个程序可以将人员添加到数组列表中 我想做的是将这些人也添加到文本文件中 但程序会覆盖第一行 因此这些人会被删除 如何告诉编译器在下一个空闲行写入 import java io import java util import javax
  • Springs 元素“beans”不能具有字符 [children],因为该类型的内容类型是仅元素

    我在 stackoverflow 中搜索了一些页面来解决这个问题 确实遵循了一些正确的答案 但不起作用 我是春天的新人 对不起 这是我的调度程序 servlet
  • com.jcraft.jsch.JSchException:身份验证失败

    当我从本地磁盘上传文件到远程服务器时 出现这样的异常 com jcraft jsch JSchException Auth fail at org apache tools ant taskdefs optional ssh Scp exe

随机推荐

  • WSS 代码执行的权限提升

    WSS 代码执行的权限提升 概述 WSS 默认使用身份模拟执行代码 也就是说用当前登录的用户身份执行Web Part或者自定义应用程序的代码访问 在大多数情况下 这种机制能够准确并严格地控制了标准权限的用户他对特定网站资源和敏感数据的访问
  • [LeetCode-35]-Search Insert Position(搜索整数所在的位置)

    文章目录 题目相关 Solution 1 顺序遍历 2 算法改进 二分查找 题目相关 题目解读 从有序整数列表中搜索给定整数 如果在其中返回下标位置 如果不在 返回应该在的位置 题目 原题链接 Given a sorted array an
  • MyBatis3 映射boolean 类型注意事项

    1 MySQL8 数据库关于boolean 存储结构定义 使用tinyint 1 代表Boolean 类型 2 实体定义关于属性字段为boolean 类型定义 3 实体属性与数据库字段映射文件配置 Mapper xml 文件 4 控制层 如
  • 你不知道的JavaScript---异步:现在与未来

    目录 异步 分块的程序 事件循环 并行线程 并发 非交互 交互 协作 任务 语句顺序 异步 js如何表达和控制持续一段时间的程序行为 分散在一段时间内运行的程序行为 持续一段时间 不是指类似于 for循环开始到结束的过程 而是指 程序的一部
  • Android 嵌套滑动总结,android基础考试题及答案

  • git 合并多个 commit

    1 rebase 介绍 rebase在git中是一个非常有魅力的命令 使用得当会极大提高自己的工作效率 相反 如果乱用 会给团队中其他人带来麻烦 它的作用简要概括为 可以对某一段线性提交历史进行编辑 删除 复制 粘贴 因此 合理使用reba
  • 数据分析(一)

    label distribution 是一个不均衡的数据集 需要做数据预处理 Sentence length distribution 句子的长度也很极端 有很多的outliers 需要对过长的数据进行舍弃或者切割
  • Eviews用向量自回归模型VAR实证分析公路交通通车里程与经济发展GDP协整关系时间序列数据和脉冲响应可视化

    最近我们被客户要求撰写关于向量自回归模型的研究报告 包括一些图形和统计输出 视频 向量自回归VAR数学原理及R软件经济数据脉冲响应分析实例 视频 向量自回归VAR数学原理及R语言软件经济数据脉冲响应分析实例 时长12 01 河源市是国务院1
  • JS函数curry(柯里化)

    原文地址 http blog jobbole com 77956 什么是柯里化 柯里化是这样的一个转换过程 把接受多个参数的函数变换成接受一个单一参数 译注 最初函数的第一个参数 的函数 如果其他的参数是必要的 返回接受余下的参数且返回结果
  • 机器学习之特征工程

    1 为什么做特征工程 我们学习编程语言时被告知程序 数据结构 算法 那么对于机器学习 我认为也可以类比为机器学习 大数据 机器学习算法 运行平台 面对一个机器学习问题 一般有两种解题思路 传统机器学习算法或者深度学习算法 一般而言 传统机器
  • Android.mk文件详解

    Android mk文件详解 Android mk 文件位于项目 jni 目录的子目录中 用于向构建系统描述源文件和共享库 它实际上是构建系统解析一次或多次的微小 GNU makefile 片段 Android mk 文件用于定义 Appl
  • 链表oj刷题——6道进阶题目

    目录 1 链表分割 题目 思路 2 链表的回文结构 题目 思路 3 输入两个链表 找出它们的第一个公共结点 题目 思路一 思路二 思路三 4 给定一个链表 判断链表中是否有环 题目 思路 5 给定一个链表 返回链表开始入环的第一个结点 如果
  • ConcurrentHashMap总结

    为什么80 的码农都做不了架构师 gt gt gt 并发编程实践中 ConcurrentHashMap是一个经常被使用的数据结构 相比于Hashtable以及Collections synchronizedMap ConcurrentHas
  • Struts2框架(一)

    Struts2框架 一 什么是框架 框架有什么用 1 框架 是 实现部分功能的代码 半成品 使用框架简化企业级软件开发 提高开发效率 2 学习框架 清楚的知道框架能做什么 还有哪些工作需要自己编码实现 二 什么是struts2框架 它有什么
  • 快速实现ML302 4G HTTP通信详解

    ML302作为HTTP Client和Server通信 一 本例程实现功能 二 Core提供的HTTP功能介绍 三 接线图 五 完整代码 代码运行结果 六 需注意事项 一 本例程实现功能 Core通过ML302 4G Cat1模块实现HTT
  • SpringBoot项目表格下载,上传和批量数据导入功能——小白级别,自己记录使用;

    应用场景 在后台管理项目中经常会需要批量导入的功能 这个时候我们就可以用Excel表格完成数据的下载 一 新建SpringBoot项目 并且配置数据库 1 pom xml 文件中导入依赖
  • 软件测试入门知识,jmeter系统基础课程———带你由浅入深学性能(完)

    软件测试知识持续更新中 性能测试常见问题 简述性能测试流程 如何确定系统最大负载 你们系统哪些地方 哪些功能 做了性能测试 你们的并发用户数是怎么确定的 你们性能测试什么时间执行 怎么分析性能测试结果 think time 的作用是什么 在
  • java复制的五种方法

    第一种 private static void methods1 throws FileNotFoundException IOException 字符流 一次读写一个字符 创建输入流对象 FileReader fr new FileRea
  • MySQL连表分组统计使用count查询出数据不准确问题解决方案

    先上两副图 这里有两张表 score表和year as表 要求统计出score表按年份分组的个数 且查询出来的内容需要包括year as表中的year as字段 使用正常连表并分组统计count得出的SQL和对应结果如下 SELECT b
  • 基于JDK1.8 的ArrayList源码分析

    基于JDK1 8 的ArrayList源码分析 代码注释 JDK版本 jdk1 8 0 181 package java util import java util function Consumer import java util fu