Java集合源码剖析——ArrayList源码剖析

ArrayList简介

ArrayList是基于数组实现的,是一个动态数组,其容量能自动增长,类似于C语言中的动态申请内存,动态增长内存。

ArrayList不是线程安全的,只能用在单线程环境下,多线程环境下可以考虑用Collections.synchronizedList(List l)函数返回一个线程安全的ArrayList类,也可以使用concurrent并发包下的CopyOnWriteArrayList类。

ArrayList实现了Serializable接口,因此它支持序列化,能够通过序列化传输,实现了RandomAccess接口,支持快速随机访问,实际上就是通过下标序号进行快速访问,实现了Cloneable接口,能被克隆。

ArrayList源码剖析

ArrayList的源码如下(加入了比较详细的注释):

 
package java.util;    
   
public class ArrayList<E> extends AbstractList<E>    
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable    
{    
    // 序列版本号    
    private static final long serialVersionUID = 8683452581122892189L;    
   
    // ArrayList基于该数组实现,用该数组保存数据   
    private transient Object[] elementData;    
   
    // ArrayList中实际数据的数量    
    private int size;    
   
    // ArrayList带容量大小的构造函数。    
    public ArrayList(int initialCapacity) {    
        super();    
        if (initialCapacity < 0)    
            throw new IllegalArgumentException("Illegal Capacity: "+    
                                               initialCapacity);    
        // 新建一个数组    
        this.elementData = new Object[initialCapacity];    
    }    
   
    // ArrayList无参构造函数。默认容量是10。    
    public ArrayList() {    
        this(10);    
    }    
   
    // 创建一个包含collection的ArrayList    
    public ArrayList(Collection<? extends E> c) {    
        elementData = c.toArray();    
        size = elementData.length;    
        if (elementData.getClass() != Object[].class)    
            elementData = Arrays.copyOf(elementData, size, Object[].class);    
    }    
   
   
    // 将当前容量值设为实际元素个数    
    public void trimToSize() {    
        modCount++;    
        int oldCapacity = elementData.length;    
        if (size < oldCapacity) {    
            elementData = Arrays.copyOf(elementData, size);    
        }    
    }    
   
   
    // 确定ArrarList的容量。    
    // 若ArrayList的容量不足以容纳当前的全部元素,设置 新的容量=“(原始容量x3)/2 + 1”    
    public void ensureCapacity(int minCapacity) {    
        // 将“修改统计数”+1,该变量主要是用来实现fail-fast机制的    
        modCount++;    
        int oldCapacity = elementData.length;    
        // 若当前容量不足以容纳当前的元素个数,设置 新的容量=“(原始容量x3)/2 + 1”    
        if (minCapacity > oldCapacity) {    
            Object oldData[] = elementData;    
            int newCapacity = (oldCapacity * 3)/2 + 1;    
            //如果还不够,则直接将minCapacity设置为当前容量  
            if (newCapacity < minCapacity)    
                newCapacity = minCapacity;    
            elementData = Arrays.copyOf(elementData, newCapacity);    
        }    
    }    
   
    // 添加元素e    
    public boolean add(E e) {    
        // 确定ArrayList的容量大小    
        ensureCapacity(size + 1);  // Increments modCount!!    
        // 添加e到ArrayList中    
        elementData[size++] = e;    
        return true;    
    }    
   
    // 返回ArrayList的实际大小    
    public int size() {    
        return size;    
    }    
   
    // ArrayList是否包含Object(o)    
    public boolean contains(Object o) {    
        return indexOf(o) >= 0;    
    }    
   
    //返回ArrayList是否为空    
    public boolean isEmpty() {    
        return size == 0;    
    }    
   
    // 正向查找,返回元素的索引值    
    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;    
        }    
   
        // 反向查找,返回元素的索引值    
        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;    
    }    
   
    // 反向查找(从数组末尾向开始查找),返回元素(o)的索引值    
    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;    
    }    
     
   
    // 返回ArrayList的Object数组    
    public Object[] toArray() {    
        return Arrays.copyOf(elementData, size);    
    }    
   
    // 返回ArrayList元素组成的数组  
    public <T> T[] toArray(T[] a) {    
        // 若数组a的大小 < ArrayList的元素个数;    
        // 则新建一个T[]数组,数组大小是“ArrayList的元素个数”,并将“ArrayList”全部拷贝到新数组中    
        if (a.length < size)    
            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;    
    }    
   
    // 获取index位置的元素值    
    public E get(int index) {    
        RangeCheck(index);    
   
        return (E) elementData[index];    
    }    
   
    // 设置index位置的值为element    
    public E set(int index, E element) {    
        RangeCheck(index);    
   
        E oldValue = (E) elementData[index];    
        elementData[index] = element;    
        return oldValue;    
    }    
   
    // 将e添加到ArrayList中    
    public boolean add(E e) {    
        ensureCapacity(size + 1);  // Increments modCount!!    
        elementData[size++] = e;    
        return true;    
    }    
   
    // 将e添加到ArrayList的指定位置    
    public void add(int index, E element) {    
        if (index > size || index < 0)    
            throw new IndexOutOfBoundsException(    
            "Index: "+index+", Size: "+size);    
   
        ensureCapacity(size+1);  // Increments modCount!!    
        System.arraycopy(elementData, index, elementData, index + 1,    
             size - index);    
        elementData[index] = element;    
        size++;    
    }    
   
    // 删除ArrayList指定位置的元素    
    public E remove(int index) {    
        RangeCheck(index);    
   
        modCount++;    
        E oldValue = (E) elementData[index];    
   
        int numMoved = size - index - 1;    
        if (numMoved > 0)    
            System.arraycopy(elementData, index+1, elementData, index,    
                 numMoved);    
        elementData[--size] = null; // Let gc do its work    
   
        return oldValue;    
    }    
   
    // 删除ArrayList的指定元素    
    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 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; // Let gc do its work    
    }    
   
    // 删除元素    
    public boolean remove(Object o) {    
        if (o == null) {    
            for (int index = 0; index < size; index++)    
            if (elementData[index] == null) {    
                fastRemove(index);    
            return true;    
            }    
        } else {    
            // 便利ArrayList,找到“元素o”,则删除,并返回true。    
            for (int index = 0; index < size; index++)    
            if (o.equals(elementData[index])) {    
                fastRemove(index);    
            return true;    
            }    
        }    
        return false;    
    }    
   
    // 清空ArrayList,将全部的元素设为null    
    public void clear() {    
        modCount++;    
   
        for (int i = 0; i < size; i++)    
            elementData[i] = null;    
   
        size = 0;    
    }    
   
    // 将集合c追加到ArrayList中    
    public boolean addAll(Collection<? extends E> c) {    
        Object[] a = c.toArray();    
        int numNew = a.length;    
        ensureCapacity(size + numNew);  // Increments modCount    
        System.arraycopy(a, 0, elementData, size, numNew);    
        size += numNew;    
        return numNew != 0;    
    }    
   
    // 从index位置开始,将集合c添加到ArrayList    
    public boolean addAll(int index, Collection<? extends E> c) {    
        if (index > size || index < 0)    
            throw new IndexOutOfBoundsException(    
            "Index: " + index + ", Size: " + size);    
   
        Object[] a = c.toArray();    
        int numNew = a.length;    
        ensureCapacity(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;    
    }    
   
    // 删除fromIndex到toIndex之间的全部元素。    
    protected void removeRange(int fromIndex, int toIndex) {    
    modCount++;    
    int numMoved = size - toIndex;    
        System.arraycopy(elementData, toIndex, elementData, fromIndex,    
                         numMoved);    
   
    // Let gc do its work    
    int newSize = size - (toIndex-fromIndex);    
    while (size != newSize)    
        elementData[--size] = null;    
    }    
   
    private void RangeCheck(int index) {    
    if (index >= size)    
        throw new IndexOutOfBoundsException(    
        "Index: "+index+", Size: "+size);    
    }    
   
   
    // 克隆函数    
    public Object clone() {    
        try {    
            ArrayList<E> v = (ArrayList<E>) super.clone();    
            // 将当前ArrayList的全部元素拷贝到v中    
            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();    
        }    
    }    
   
   
    // java.io.Serializable的写入函数    
    // 将ArrayList的“容量,所有的元素值”都写入到输出流中    
    private void writeObject(java.io.ObjectOutputStream s)    
        throws java.io.IOException{    
    // Write out element count, and any hidden stuff    
    int expectedModCount = modCount;    
    s.defaultWriteObject();    
   
        // 写入“数组的容量”    
        s.writeInt(elementData.length);    
   
    // 写入“数组的每一个元素”    
    for (int i=0; i<size; i++)    
            s.writeObject(elementData[i]);    
   
    if (modCount != expectedModCount) {    
            throw new ConcurrentModificationException();    
        }    
   
    }    
   
   
    // java.io.Serializable的读取函数:根据写入方式读出    
    // 先将ArrayList的“容量”读出,然后将“所有的元素值”读出    
    private void readObject(java.io.ObjectInputStream s)    
        throws java.io.IOException, ClassNotFoundException {    
        // Read in size, and any hidden stuff    
        s.defaultReadObject();    
   
        // 从输入流中读取ArrayList的“容量”    
        int arrayLength = s.readInt();    
        Object[] a = elementData = new Object[arrayLength];    
   
        // 从输入流中将“所有的元素值”读出    
        for (int i=0; i<size; i++)    
            a[i] = s.readObject();    
    }    
}

几点总结

关于ArrayList的源码,给出几点比较重要的总结:

1、注意其三个不同的构造方法。无参构造方法构造的ArrayList的容量默认为10,带有Collection参数的构造方法,将Collection转化为数组赋给ArrayList的实现数组elementData。

2、注意扩充容量的方法ensureCapacity。ArrayList在每次增加元素(可能是1个,也可能是一组)时,都要调用该方法来确保足够的容量。当容量不足以容纳当前的元素个数时,就设置新的容量为旧的容量的1.5倍加1,如果设置后的新容量还不够,则直接新容量设置为传入的参数(也就是所需的容量),而后用Arrays.copyof()方法将元素拷贝到新的数组(详见下面的第3点)。从中可以看出,当容量不够时,每次增加元素,都要将原来的元素拷贝到一个新的数组中,非常之耗时,也因此建议在事先能确定元素数量的情况下,才使用ArrayList,否则建议使用LinkedList。

3、ArrayList的实现中大量地调用了Arrays.copyof()和System.arraycopy()方法。我们有必要对这两个方法的实现做下深入的了解。

首先来看Arrays.copyof()方法。它有很多个重载的方法,但实现思路都是一样的,我们来看泛型版本的源码:

 public static <T> T[] copyOf(T[] original, int newLength) {  
     return (T[]) copyOf(original, newLength, original.getClass());  
 }

很明显调用了另一个copyof方法,该方法有三个参数,最后一个参数指明要转换的数据的类型,其源码如下:

 public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {  
     T[] copy = ((Object)newType == (Object)Object[].class)  
         ? (T[]) new Object[newLength]  
         : (T[]) Array.newInstance(newType.getComponentType(), newLength);  
     System.arraycopy(original, 0, copy, 0,  
                      Math.min(original.length, newLength));  
     return copy;  
 }

这里可以很明显地看出,该方法实际上是在其内部又创建了一个长度为newlength的数组,调用System.arraycopy()方法,将原来数组中的元素复制到了新的数组中。

下面来看System.arraycopy()方法。该方法被标记了native,调用了系统的C/C++代码,在JDK中是看不到的,但在openJDK中可以看到其源码。该函数实际上最终调用了C语言的memmove()函数,因此它可以保证同一个数组内元素的正确复制和移动,比一般的复制方法的实现效率要高很多,很适合用来批量处理数组。Java强烈推荐在复制大量数组元素时用该方法,以取得更高的效率。

4、注意ArrayList的两个转化为静态数组的toArray方法。

第一个,Object[] toArray()方法。该方法有可能会抛出java.lang.ClassCastException异常,如果直接用向下转型的方法,将整个ArrayList集合转变为指定类型的Array数组,便会抛出该异常,而如果转化为Array数组时不向下转型,而是将每个元素向下转型,则不会抛出该异常,显然对数组中的元素一个个进行向下转型,效率不高,且不太方便。

第二个,<T> T[] toArray(T[] a)方法。该方法可以直接将ArrayList转换得到的Array进行整体向下转型(转型其实是在该方法的源码中实现的),且从该方法的源码中可以看出,参数a的大小不足时,内部会调用Arrays.copyOf方法,该方法内部创建一个新的数组返回,因此对该方法的常用形式如下:

 public static Integer[] vectorToArray2(ArrayList<Integer> v) {    
     Integer[] newText = (Integer[])v.toArray(new Integer[0]);    
     return newText;    
 }

5、ArrayList基于数组实现,可以通过下标索引直接查找到指定位置的元素,因此查找效率高,但每次插入或删除元素,就要大量地移动元素,插入删除元素的效率低。

6、在查找给定元素索引值等的方法中,源码都将该元素的值分为null和不为null两种情况处理,ArrayList中允许元素为null。

初始注释解析

Resizable-array implementation of the List interface. Implements all optional list operations, and permits all elements, including null. In addition to implementing the 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 Vector, except that it is unsynchronized.)

The size, isEmpty, get, set, iterator, and listIterator operations run in constant time. The add operation runs in amortized constant time, 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 LinkedList implementation.

Each ArrayList instance has a capacity. 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.

An application can increase the capacity of an ArrayList instance before adding a large number of elements using the ensureCapacity operation. This may reduce the amount of incremental reallocation.

 // 创建一个动态数组
 ArrayList<String> sites = new ArrayList<>();
 ​
 // 设置 arraylist的容量大小
 sites.ensureCapacity(3);
 ​
 sites.add("Google");
 sites.add("Runoob");
 sites.add("Taobao");
 System.out.println("网站列表: " + sites);

Note that this implementation is not synchronized. If multiple threads access an ArrayList instance concurrently, and at least one of the threads modifies the list structurally, it must 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 Collections.synchronizedList method. This is best done at creation time, to prevent accidental unsynchronized access to the list:

/*

这通常是通过同步一些自然封装列表的对象来完成的。如果不存在这样的对象,则应使用 Collections.synchronizedList 方法“包装”该列表。这最好在创建时完成,以防止对列表的意外不同步访问:

*/

 List list = Collections.synchronizedList(new ArrayList(...));

The iterators returned by this class's iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a 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.

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 ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs.

IDEA翻译插件

1、设置->插件->translator,安装

2、文件路径 C:\Windows\System32\drivers\etc

本地hosts文件添加下面配置

 203.208.40.66 translate.google.com
 203.208.40.66 translate.googleapis.com

保存,成功!

新源码

 private static final int DEFAULT_CAPACITY = 10;    

Shared empty array instance used for empty instances.(用于空实例的共享空数组实例。)

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 = {};

The size of the ArrayList (the number of elements it contains).(ArrayList 的大小(它包含的元素数量)。)

private int size;

Constructs an empty list with the specified initial capacity. 形参: initialCapacity – the initial capacity of the list 抛出: IllegalArgumentException – if the specified initial capacity is negative

(构造一个具有指定初始容量的空列表。

形参:

***initialCapacity*** – 列表的初始容量

抛出:

IllegalArgumentException – 如果指定的初始容量为负)

public ArrayList(int initialCapacity) {
    if (initialCapacity > 0) {
        this.elementData = new Object[initialCapacity];
    } else if (initialCapacity == 0) {
        this.elementData = EMPTY_ELEMENTDATA;
    } else {
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    }
}

Constructs an empty list with an initial capacity of ten.(构造一个初始容量为 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. 形参: c – the collection whose elements are to be placed into this list 抛出: NullPointerException – if the specified collection is null

(按照集合的迭代器返回的顺序构造一个包含指定集合元素的列表。)

public ArrayList(Collection<? extends E> c) {
    Object[] a = c.toArray();
    if ((size = a.length) != 0) {
        if (c.getClass() == ArrayList.class) {
            elementData = a;
        } else {
            elementData = Arrays.copyOf(a, size, Object[].class);
        }
    } else {
        // replace with empty array.
        elementData = EMPTY_ELEMENTDATA;
    }
}

Trims the capacity of this ArrayList instance to be the list's current size. An application can use this operation to minimize the storage of an ArrayList instance.(将此 ArrayList 实例的容量修剪为列表的当前大小。应用程序可以使用此操作来最小化 ArrayList 实例的存储。)

public void trimToSize() {
    modCount++;
    if (size < elementData.length) {
        elementData = (size == 0)
          ? EMPTY_ELEMENTDATA
          : Arrays.copyOf(elementData, size);
    }
}

Increases the capacity of this ArrayList instance, if necessary, to ensure that it can hold at least the number of elements specified by the minimum capacity argument.(如有必要,增加此 ArrayList 实例的容量,以确保它至少可以容纳最小容量参数指定的元素数量。)

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);
    }
}
//计算容量
private static int calculateCapacity(Object[] elementData, int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    return minCapacity;
}
//确保内部容量
private void ensureCapacityInternal(int minCapacity) {
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}

//确保显式容量
private void ensureExplicitCapacity(int minCapacity) {
    modCount++;

    // overflow-conscious code
    if (minCapacity - elementData.length > 0)
        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(要分配的数组的最大大小。一些 VM 在数组中保留一些标题字。尝试分配更大的数组可能会导致 OutOfMemoryError:请求的数组大小超过 VM 限制)

private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
//2147483647 - 8

Increases the capacity to ensure that it can hold at least the number of elements specified by the minimum capacity argument.(增加容量以确保它至少可以容纳最小容量参数指定的元素数量。)

private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    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);
}

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.

public int size() {
    return size;
}

Returns true if this list contains no elements.

public boolean isEmpty() {
    return size == 0;
}

Returns true if this list contains the specified element. More formally, returns true if and only if this list contains at least one element e such that (o==null ? e==null : o.equals(e)).(当且仅当此列表包含至少一个元素 e 时才返回 true)

public boolean contains(Object o) {
    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 i such that(o==null ? get(i)==null : o.equals(get(i))), or -1 if there is no such index.(返回此列表中指定元素第一次出现的索引,如果此列表不包含该元素,则返回 -1。更正式地说,返回满足 (o==null ? get(i)==null : o.equals(get(i))) 的最低索引 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;
}

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 i such that (o==null ? get(i)==null : o.equals(get(i))), or -1 if there is no such index.(返回此列表中指定元素最后一次出现的索引,如果此列表不包含该元素,则返回 -1。更正式地说,返回满足 (o==null ? get(i)==null : o.equals(get(i))) 的最高索引 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 ArrayList instance. (The elements themselves are not copied.)(返回此 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). 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. This method acts as bridge between array-based and collection-based APIs.(以正确的顺序(从第一个元素到最后一个元素)返回包含此列表中所有元素的数组。返回的数组将是“安全的”,因为此列表不维护对它的引用。 (换句话说,这个方法必须分配一个新数组)。因此,调用者可以自由修改返回的数组。此方法充当基于数组和基于集合的 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.(以正确的顺序(从第一个元素到最后一个元素)返回一个包含此列表中所有元素的数组;返回数组的运行时类型是指定数组的运行时类型。如果列表适合指定的数组,则在其中返回。否则,将使用指定数组的运行时类型和此列表的大小分配一个新数组。)

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 null. (This is useful in determining the length of the list only if the caller knows that the list does not contain any null elements.)(如果列表适合指定的数组并有剩余空间(即,数组的元素多于列表),则数组中紧跟集合末尾的元素设置为 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;
}

Returns the element at the specified position in this list.(返回此列表中指定位置的元素。)

public E get(int index) {
    rangeCheck(index);

    return elementData(index);
}

Replaces the element at the specified position in this list with the specified element.(将此列表中指定位置的元素替换为指定元素。)

public E set(int index, E element) {
    rangeCheck(index);

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

Appends the specified element to the end of this list.(将指定元素附加到此列表的末尾。)

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    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).(在此列表中的指定位置插入指定元素。将当前位于该位置的元素(如果有)和任何后续元素向右移动(将其索引加一)。)

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

/*

将指定源数组中的数组从指定位置开始复制到目标数组的指定位置。数组组件的子序列从src引用的源数组复制到dest引用的目标数组。复制的组件数量等于length参数。源数组中位置srcPos到 srcPos+length- srcPos+length-1的分量被分别复制到目标数组的位置destPos到destPos+length-1中。 如果src和dest参数引用相同的数组对象,则执行复制,就好像首先将位置srcPos到srcPos+length-1的分量复制到具有length分量的临时数组,然后临时数组的内容是通过目标数组的destPos+length-1复制到位置destPos 。

否则,如果从位置srcPos到srcPos+length-1的源数组的任何实际组件不能通过赋值转换转换为目标数组的组件类型,则抛出ArrayStoreException 。在这种情况下,设k为小于 length 的最小非负整数,使得src[srcPos+ k ]不能转换为目标数组的组件类型;当抛出异常时,从位置srcPos到srcPos+ k -1的源数组组件将已经被复制到目标数组位置destPos到destPos+ k -1 ,并且不会修改目标数组的其他位置。 (由于已经逐条列出了限制,本段仅适用于两个数组都具有引用类型的组件类型的情况。)

src - 源数组。
srcPos – 源数组中的起始位置。
dest - 目标数组。
destPos – 目标数据中的起始位置。
length – 要复制的数组元素的数量。

找到添加的元素,后面的元素进行复制,添加后将后续复制的元素进行添加

*/

Removes the element at the specified position in this list. Shifts any subsequent elements to the left (subtracts one from their indices).(移除此列表中指定位置的元素。将任何后续元素向左移动(从它们的索引中减去 1)。)

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

    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 i such that (o==null ? get(i)==null : o.equals(get(i))) (if such an element exists). Returns true if this list contained the specified element (or equivalently, if this list changed as a result of the call).(从此列表中删除第一次出现的指定元素(如果存在)。如果列表不包含该元素,则它不变。更正式地说,删除具有最低索引 i 的元素,使得 (o==null ? get(i)==null : o.equals(get(i))) (如果存在这样的元素)。如果此列表包含指定的元素(或等效地,如果此列表因调用而更改),则返回 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;
}

快速删除

/*
* Private remove method that skips bounds checking and does not
* return the value removed.
*/
private void fastRemove(int index) {
    modCount++;
    int numMoved = size - index - 1;
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index,
                         numMoved);
    elementData[--size] = null; // clear to let GC do its work
}

Removes all of the elements from this list. The list will be empty after this call returns.(删除所有)

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.)(按照指定集合的迭代器返回的顺序,将指定集合中的所有元素附加到此列表的末尾。如果在操作正在进行时修改了指定的集合,则此操作的行为是未定义的。 (这意味着如果指定的集合是这个列表,并且这个列表是非空的,那么这个调用的行为是未定义的。))

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

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.(将指定集合中的所有元素插入此列表,从指定位置开始。将当前位于该位置的元素(如果有)和任何后续元素向右移动(增加它们的索引)。新元素将按照指定集合的迭代器返回的顺序出现在列表中。)

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

Removes from this list all of the elements whose index is between fromIndex, inclusive, and toIndex, exclusive. Shifts any succeeding elements to the left (reduces their index). This call shortens the list by (toIndex - fromIndex) elements. (If toIndex==fromIndex, this operation has no effect.)(从此列表中删除索引在 fromIndex(包括)和 toIndex(不包括)之间的所有元素。将任何后续元素向左移动(减少它们的索引)。此调用通过 (toIndex - fromIndex) 元素缩短列表。 (如果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;  //将所有要删除的元素设置为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.(检查给定的索引是否在范围内。如果不是,则引发适当的运行时异常。此方法不检查索引是否为负:它总是在数组访问之前立即使用,如果索引为负,则抛出 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 详细消息。在错误处理代码的许多可能重构中,这种“大纲”在服务器和客户端 VM 上表现最好。)

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

Removes from this list all of its elements that are contained in the specified collection.(删除其中的列表)

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

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.(仅保留此列表中包含在指定集合中的元素。换句话说,从这个列表中删除所有不包含在指定集合中的元素。只要目标数列中的元素,其他全都删掉)

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;  //中间要删除的设置为null
            modCount += size - w;
            size = w;
            modified = true;
        }
    }
    return modified;
}

Save the state of the ArrayList instance to a stream (that is, serialize it).(将 ArrayList 实例的状态保存到流中(即序列化它)。)

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 ArrayList instance from a stream (that is, deserialize it).(从流中重构 ArrayList 实例(即反序列化它)。)

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 next. An initial call to previous would return the element with the specified index minus one.(返回此列表中元素的列表迭代器(以正确的顺序),从列表中的指定位置开始。指定的索引指示初始调用 next 将返回的第一个元素。对 previous 的初始调用将返回具有指定索引减一的元素。)

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).(返回此列表中元素的列表迭代器(以正确的顺序)。)

public ListIterator<E> listIterator() {
    return new ListItr(0);
}

Returns an iterator over the elements in this list in proper sequence.(以正确的顺序返回此列表中元素的迭代器。)

public Iterator<E> iterator() {
    return new 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();
    }
}

Returns a view of the portion of this list between the specified fromIndex, inclusive, and toIndex, exclusive. (If fromIndex and 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.(返回此列表在指定的 fromIndex(包括)和 toIndex(不包括)之间的部分的视图。 (如果 fromIndex 和 toIndex 相等,则返回列表为空。)返回列表由此列表支持,因此返回列表中的非结构性更改会反映在此列表中,反之亦然。返回的列表支持所有可选的列表操作。)

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:(这种方法消除了显式范围操作的需要(通常存在于数组中的那种)。通过传递 subList 视图而不是整个列表,任何需要列表的操作都可以用作范围操作。例如,以下习惯用法从列表中删除一系列元素:)

list.subList(from, to).clear();

Similar idioms may be constructed for indexOf(Object) and lastIndexOf(Object), and all of the algorithms in the Collections class can be applied to a subList.(可以为 indexOf(Object) 和 lastIndexOf(Object) 构造类似的习语,并且 Collections 类中的所有算法都可以应用于子列表。)

The semantics of the list returned by this method become undefined if the backing list (i.e., this list) is structurally modified 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.)(如果后备列表(即此列表)以除通过返回列表之外的任何方式进行结构修改,则此方法返回的列表的语义将变为未定义。 (结构修改是改变这个列表的大小,或者以其他方式扰乱它,使得正在进行的迭代可能会产生不正确的结果。))

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();
    }
}
sites.forEach(e -> {e = e + "aaa"; System.out.println("e = " + e);} );

输出结果为:
    原[ads, qee, ads, qee]
    现e = adsaaa
	  e = qeeaaa
	  e = adsaaa
	  e = qeeaaa
@Override
public Spliterator<E> spliterator() {
    return new ArrayListSpliterator<>(this, 0, -1, 0);
}

Spliterator<String> spliterator = sites.spliterator();
System.out.println("spliterator = " + spliterator.characteristics());
spliterator.forEachRemaining(n -> System.out.println(n));
输出结果为:
网站列表: [Google, Runoob, Taobao]
spliterator = 16464
Google
Runoob
Taobao  

判断条件进行删除

@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;
}
sites.removeIf(e -> e.contains("bao"));
输出结果为:
Google
Runoob
Taobao
[Google, Runoob]

对元素进行转换

@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++;
}
sites.replaceAll(e -> e.toUpperCase(Locale.ROOT));
System.out.println(sites);
运行结果:
    [GOOGLE, RUNOOB]

对元素进行比较后输出

 @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++;
 }
 sites.sort(Comparator.naturalOrder());
 System.out.println("升序 = " + sites);
 sites.sort(Comparator.reverseOrder());
 System.out.println("降序 = " + sites);
 ​
 运行结果:
     网站列表: [Google, Runoob, Taobao, Wiki]
     升序 = [Google, Runoob, Taobao, Wiki]
     降序 = [Wiki, Taobao, Runoob, Google]

初始容量大小

 // 设置 arraylist的初始容量大小
 //动态数组,如果有第四个元素进list则会自动增加容量
 sites.ensureCapacity(3);
 ​
 System.out.println(sites.size());
 ​
 sites.add("Google");
 sites.add("Runoob");
 sites.add("Taobao");
 sites.add("Wiki");
 System.out.println(sites.size());
 ​
 运行结果:
     0
     4
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值