
【JDK源码分析系列】ArrayList源码分析
发布日期:2021-05-07 20:53:54
浏览次数:24
分类:原创文章
本文共 67253 字,大约阅读时间需要 224 分钟。
【JDK源码分析系列】ArrayList源码分析
【0】ArrayList 整体架构图示
【1】ArrayList源码MCL视图
ArrayList的MCL视图如下图所示,包括内部类的MCL视图;
【2】ArrayList源码分析相关知识点总结
/** * 如果用transient声明一个实例变量,当对象存储时,它的值不需要维持; * 即用transient关键字标记的成员变量不参与序列化过程; * * 此处使用transient关键的原因在于: * ArrayList在序列化的时候会调用writeObject,反序列化时调用readObject 也就是自定义序列化 * 因为ArrayList数组elementData中有未使用的空间 ,如果没有使用的空间也序列化,势必会影响性能 */ transient Object[] elementData;
一:快速失败(fail—fast) 在用迭代器遍历一个集合对象时,如果遍历过程中对集合对象的内容进行了修改(增加、删除、修改),则会抛出Concurrent Modification Exception。 原理:迭代器在遍历时直接访问集合中的内容,并且在遍历过程中使用一个 modCount 变量。集合在被遍历期间如果内容发生变化,就会改变modCount的值。 每当迭代器使用hashNext()/next()遍历下一个元素之前,都会检测modCount变量是否为expectedmodCount值,是的话就返回遍历;否则抛出异常,终止遍历。 注意:这里异常的抛出条件是检测到 modCount!=expectedmodCount 这个条件。如果集合发生变化时修改modCount值刚好又设置为了expectedmodCount值,则异常不会抛出。因此,不能依赖于这个异常是否抛出而进行并发操作的编程,这个异常只建议用于检测并发修改的bug。 场景:java.util包下的集合类都是快速失败的,不能在多线程下发生并发修改(迭代过程中被修改)。 二:安全失败(fail—safe) 采用安全失败机制的集合容器,在遍历时不是直接在集合内容上访问的,而是先复制原有集合内容,在拷贝的集合上进行遍历。 原理:由于迭代时是对原集合的拷贝进行遍历,所以在遍历过程中对原集合所作的修改并不能被迭代器检测到,所以不会触发Concurrent Modification Exception。 缺点:基于拷贝内容的优点是避免了Concurrent Modification Exception,但同样地,迭代器并不能访问到修改后的内容,即:迭代器遍历的是开始遍历那一刻拿到的集合拷贝,在遍历期间原集合发生的修改迭代器是不知道的。 场景:java.util.concurrent包下的容器都是安全失败,可以在多线程下并发使用,并发修改。
ArrayList集合实现RandomAccess接口有何作用RandomAccess接口是一个标志接口只要List集合实现这个接口,就能支持快速随机访问RandomAccess接口这个空架子的存在,是为了能够更好地判断集合是否ArrayList或者LinkedList,从而能够更好选择更优的遍历方式,提高性能
System.arraycopy()方法的深拷贝与浅拷贝1. 当数组为一维数组,且元素为基本类型或String类型时,属于深复制,即原数组与新数组的元素不会相互影响2. 当数组为多维数组,或一维数组中的元素为引用类型时,属于浅复制,原数组与新数组的元素引用指向同一个对象
【3】ArrayList源码注解
package java.util;import java.util.function.Consumer;import java.util.function.Predicate;import java.util.function.UnaryOperator;/** * 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 */// 时间复杂度// 新增或删除方法对数组元素的操作, 只需要根据数组索引, 直接新增和删除, 所以时间复杂度是 O(1)// 线程安全// 只有当 ArrayList 作为共享变量时, 才会有线程安全问题, 当 ArrayList 是方法内的局部变量时是没有线程安全的问题的// ArrayList 有线程安全问题的本质 : // ArrayList 自身的 elementData、size、modConut 在进行各种操作时, 都没有加锁, // 而且这些变量的类型并非是可见 (volatile) 的,// 所以如果多个线程对这些变量进行操作时可能会有值被覆盖的情况// 类注释的关键点 :// 1. 允许 put null 值,会自动扩容// 2. size、isEmpty、get、set、add 等方法时间复杂度都是 O(1)// 3. 非线程安全的,多线程情况下,推荐使用线程安全类 Collections#synchronizedList// 4. 增强 for 循环,或者使用迭代器迭代过程中,如果数组大小被改变,会快速失败,抛出异常public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable{ private static final long serialVersionUID = 8683452581122892189L; /** * Default initial capacity. */ private static final int DEFAULT_CAPACITY = 10; /** * Shared empty array instance used for empty instances. */ private static final Object[] EMPTY_ELEMENTDATA = {}; /** * The array buffer into which the elements of the ArrayList are stored. * The capacity of the ArrayList is the length of this array buffer. Any * empty ArrayList with elementData == EMPTY_ELEMENTDATA will be expanded to * DEFAULT_CAPACITY when the first element is added. */ /** * 如果用transient声明一个实例变量,当对象存储时,它的值不需要维持; * 即用transient关键字标记的成员变量不参与序列化过程; * * 此处使用transient关键的原因在于: * ArrayList在序列化的时候会调用writeObject,反序列化时调用readObject 也就是自定义序列化 * 因为ArrayList数组elementData中有未使用的空间 ,如果没有使用的空间也序列化,势必会影响性能 */ transient Object[] elementData; // non-private to simplify nested class access /** * The size of the ArrayList (the number of elements it contains). * * @serial */ private int size; /** * Constructs an empty list with the specified initial capacity. * * @param initialCapacity the initial capacity of the list * @throws IllegalArgumentException if the specified initial capacity * is negative */ /** * ArrayList构造方法 * 此方法初始化一个initialCapacity大小的Object类型数组并赋值给成员变量elementData */ public ArrayList(int initialCapacity) { super(); if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); this.elementData = new Object[initialCapacity]; } /** * Constructs an empty list with an initial capacity of ten. */ /** * 无参初始化 * * ArrayList构造方法 * 此方法构造一个空的Object数组 */ // ArrayList 无参构造器初始化时,默认大小是空数组,并不是大家常说的 10, // 10 是在第一次 add 的时候扩容的数组值 public ArrayList() { super(); this.elementData = EMPTY_ELEMENTDATA; } /** * 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 * @throws NullPointerException if the specified collection is null */ /** * <? extends E> 是 Upper Bound(上限) 的通配符; * 此处表明集合中元素的上限为E,即集合中的元素类型只能是E或E的子类 * * <? super E> 是 Lower Bound(下限) 的通配符; * 此处用来限制元素的类型下限为E,即集合中的元素类型只能是E或E的父类 * * c.toArray():调用Collection接口中的toArray()方法,将集合转化为Array */ // 指定初始数据初始化 public ArrayList(Collection<? extends E> c) { // elementData 是保存数组的容器,默认为 null elementData = c.toArray(); if ((size = elementData.length) != 0) { // c.toArray might (incorrectly) not return Object[] (see 6260652) // 这是 Java 的一个 bug,意思是当给定集合内的元素不是 Object 类型时, // 我们会转化成 Object 的类型 // BUG 触发条件 : ArrayList 初始化之后(ArrayList 元素非 Object 类型), // 再次调用 toArray 方法,得到 Object 数组,并且往 Object 数组赋值时, // 才会触发此 bug /** * 若elementData的class类型不是Object[]类型, * 则将elementData的class类型转换为Object[]类型,保留原始数组的数据 * 此处的处理目的是确保elementData的类型为Object[] */ if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } else { // replace with empty array. this.elementData = EMPTY_ELEMENTDATA; } } /** * 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的大小 * 当size小于elementData.length,则取elementData前size个元素重新对elementData赋值 */ public void trimToSize() { modCount++; if (size < elementData.length) { elementData = Arrays.copyOf(elementData, size); } } /** * 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. * * @param minCapacity the desired minimum capacity */ /** * 该方法对当前ArrayList容量进行扩容以确保至少可以保存当前所有的元素; * 当elementData为EMPTY_ELEMENTDATA时,minExpand为DEFAULT_CAPACITY,否则minExpand为0; * minCapacity大于minExpand时,调用ensureExplicitCapacity方法确定更精确的容量; */ public void ensureCapacity(int minCapacity) { int minExpand = (elementData != EMPTY_ELEMENTDATA) // any size if real element table ? 0 // larger than default for empty table. It's already supposed to be // at default size. : DEFAULT_CAPACITY; if (minCapacity > minExpand) { ensureExplicitCapacity(minCapacity); } } /** * 该方法对当前ArrayList容量进行扩容以确保至少可以保存当前所有的元素; * 该方法为ArrayList内部使用的扩容方法; */ private void ensureCapacityInternal(int minCapacity) { // 如果初始化数组大小时, 有给定初始值, 以给定的大小为准, 不走 if 逻辑 if (elementData == EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } // 确保容积足够 ensureExplicitCapacity(minCapacity); } /** * minCapacity比elementData容量大时,对elementData扩容 */ 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 */ private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; /** * Increases the capacity to ensure that it can hold at least the * number of elements specified by the minimum capacity argument. * * @param minCapacity the desired minimum capacity */ /** * 扩容并把现有数据拷贝到新的数组里面去 * 扩容策略为将原有的elementData的容量扩充1.5倍 * elementData的容量的最大值为Integer.MAX_VALUE */ private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; // oldCapacity >> 1 是把 oldCapacity 除以 2 的意思 int newCapacity = oldCapacity + (oldCapacity >> 1); // 如果扩容后的值 < 我们的期望值, 扩容后的值就等于我们的期望值 if (newCapacity - minCapacity < 0) newCapacity = minCapacity; // 如果扩容后的值 > jvm 所能分配的数组的最大值,那么就用 Integer 的最大值 if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: // 通过复制进行扩容 // 一下该行代码描述的本质是数组之间的拷贝, 扩容是会先新建一个符合我们预期容量的新数组, 然后把老数组的数据拷贝过去, // 我们通过 System.arraycopy 方法进行拷贝,此方法是 native 的方法 // /** // * @param src 被拷贝的数组 // * @param srcPos 从数组那里开始 // * @param dest 目标数组 // * @param destPos 从目标数组那个索引位置开始拷贝 // * @param length 拷贝的长度 // * 此方法是没有返回值的,通过 dest 的引用进行传值 // */ // public static native void arraycopy(Object src, int srcPos, // Object dest, int destPos, // int length); // // System.arraycopy(elementData, 0, newElementData, 0,Math.min(elementData.length,newCapacity)); // elementData = Arrays.copyOf(elementData, newCapacity); } /** * hugeCapacity为静态方法 * 静态方法一般用于对静态属性进行操作 * 此处对MAX_ARRAY_SIZE,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. * * @return the number of elements in this list */ /** * 该方法用于返回当前ArrayList的容量 */ public int size() { return size; } /** * Returns <tt>true</tt> if this list contains no elements. * * @return <tt>true</tt> if this list contains no elements */ /** * 该方法用于判断当前ArrayList是否为空 */ 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 ? e==null : o.equals(e))</tt>. * * @param o element whose presence in this list is to be tested * @return <tt>true</tt> if this list contains the specified element */ /** * 该方法用于判断ArrayList中是否包含特定的元素 */ 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 <tt>i</tt> such that * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>, * or -1 if there is no such index. */ /** * 该方法用于查找元素在ArrayList中的索引 * 分元素为NULL与非NULL两种情况进行讨论 */ 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 <tt>i</tt> such that * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>, * or -1 if there is no such index. */ /** * 该方法返回元素在ArrayList中的最后一个索引 */ 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 */ /** * 父类中的clone方法是native的; * native方法,Native Method是一个java调用非java代码的接口; * * 该方法功能: * 1.调用Object中的clone()方法并强转为一个ArrayList对象; * 2.拷贝当前ArrayList中的元素到拷贝的对象,并返回clone()方法新建的对象; */ 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. * * @return an array containing all of the elements in this list in * proper sequence */ /** * 该方法将ArrayList转换为Object[]类型的数组 */ 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 */ /** * 该方法将ArrayList转换为T[]类型的数组 * 当入参数组的容量大于当前ArrayList的容量时,T[]类型的数组多余的元素为NULL * * unchecked: 执行了未检查的转换时的警告,此处抑制该警告的产生; */ @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 /** * 该方法获取ArrayList指定索引的元素 */ @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 * @return the element at the specified position in this list * @throws IndexOutOfBoundsException {@inheritDoc} */ /** * 该方法获取ArrayList指定索引的元素 * 其中对索引作了范围检查 */ 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 * @param element element to be stored at the specified position * @return the element previously at the specified position * @throws IndexOutOfBoundsException {@inheritDoc} */ /** * 该方法在ArrayList指定索引处设置入参元素 * 其中对索引作了范围检查 */ 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. * * @param e element to be appended to this list * @return <tt>true</tt> (as specified by {@link Collection#add}) */ /** * 该方法向ArrayList中添加元素,该元素添加到ArrayList的尾部 * ensureCapacityInternal(size + 1):确保ArrayList存在足够的存储容量; */ public boolean add(E e) { // 确保数组大小是否足够,不够执行扩容,size 为当前数组的大小 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). * * @param index index at which the specified element is to be inserted * @param element element to be inserted * @throws IndexOutOfBoundsException {@inheritDoc} */ /** * 该方法在ArrayList的指定位置添加指定的元素; * ensureCapacityInternal(size + 1):确保ArrayList存在足够的存储容量; * 将index之后的元素后移一位,并在index处赋值; */ 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). * * @param index the index of the element to be removed * @return the element that was removed from the list * @throws IndexOutOfBoundsException {@inheritDoc} */ /** * 该方法在ArrayList的指定位置删除指定的元素; * 将index之后元素前移一位,并将最后一位元素赋值为NULL; * 同时改变size大小并返回删除的元素; */ 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 * <tt>i</tt> such that * <tt>(o==null ? get(i)==null : 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). * * @param o element to be removed from this list, if present * @return <tt>true</tt> if this list contained the specified element */ /** * 该方法删除ArrayList中指定的元素; * 入参对象为NULL时,删除elementData中第一个为NULL的元素 * 入参对象不为NULL时,elementData存在入参对象变将其删除 * elementData不存在入参对象时返回false; */ // 注意点 : // 1. 新增的时候是没有对 null 进行校验的, 所以删除的时候也是允许删除 null 值 // 2. 找到值在数组中的索引位置, 是通过 equals 来判断的, 如果数组元素不是基本类型, // 需要我们关注 equals 的具体实现 public boolean remove(Object o) { // 如果要删除的值是 null,找到第一个值是 null 的删除 if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); return true; } } else { // 如果要删除的值不为 null,找到第一个和要删除的值相等的删除 for (int index = 0; index < size; index++) // 这里是根据 equals 来判断值相等的, 相等后再根据索引位置进行删除 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. */ /** * 该方法删除指定索引处的元素 * 将index之后元素前移一位,并将最后一位元素赋值为NULL,同时改变size大小; */ private void fastRemove(int index) { // 记录数组的结构要发生变动了 modCount++; // numMoved 表示删除 index 位置的元素后,需要从 index 后移动多少个元素到前面去 // 减 1 的原因, 是因为 size 从 1 开始算起, index 从 0开始算起 int numMoved = size - index - 1; if (numMoved > 0) // 从 index + 1 位置开始被拷贝,拷贝的起始位置是 index,长度是 numMoved System.arraycopy(elementData, index+1, elementData, index, numMoved); // 数组最后一个位置赋值 null,帮助 GC 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. */ /** * 该方法遍历elementData,将其中的元素赋值为NULL,并将size清零 */ 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 * @return <tt>true</tt> if this list changed as a result of the call * @throws NullPointerException if the specified collection is null */ /** * 该方法在ArrayList尾部添加集合对象; * 先将集合对象转化为数组,在进行元素拷贝; */ 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. * * @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 */ /** * 该方法在ArrayList指定的索引处添加集合对象 * 将索引后的元素统一后移入参元素长度,并在索引处做元素拷贝 */ 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 * {@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}) */ /** * 该方法从ArrayList中删除一定范围内的元素; * 1.对elementData做toIndex到fromIndex的元素拷贝; * 2.将原elementData因拷贝而空出的元素赋值为NULL,调整size; */ 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. */ /** * 该方法索引范围的正确性,存在索引溢出则抛出IndexOutOfBoundsException; */ private void rangeCheck(int index) { if (index >= size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } /** * A version of rangeCheck used by add and addAll. */ /** * 该方法索引范围的正确性,存在索引溢出或index为负时则抛出IndexOutOfBoundsException; */ 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. */ /** * 该方法构造outOfBoundsMsg字符串 */ 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. * * @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) */ /** * Objects.requireNonNull(c):判断对象非NULL; * 从此列表中移除包含在指定集合中的所有元素; */ 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. * * @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) */ /** * Objects.requireNonNull(c):判断对象非NULL; * 从此列表中保留包含在指定集合中的所有元素; */ public boolean retainAll(Collection<?> c) { Objects.requireNonNull(c); return batchRemove(c, true); } /** * c.contains(elementData[r]):判断集合中是否包含指定的元素;true,包含;false,不包含; * elementData[w++] = elementData[r];:将待保留的元素前移; * elementData[i] = null;:将元素前移后多余的空间清空赋值NULL,调整size; */ private boolean batchRemove(Collection<?> c, boolean complement) { final Object[] elementData = this.elementData; int r = 0, w = 0; boolean modified = false; try { for (; r < size; r++) if (c.contains(elementData[r]) == complement) elementData[w++] = elementData[r]; } finally { // Preserve behavioral compatibility with AbstractCollection, // even if c.contains() throws. /** * 确保异常抛出前的部分可以完成期望的操作 * r!=size原因:c.contains(elementData[r])可能会抛出异常 */ if (r != size) { System.arraycopy(elementData, r, elementData, w, size - r); w += size - r; } /** * w!=size时,即使try块抛出异常,也能正确处理异常抛出前的操作, * w始终为待保存的前段部分,数组不会因此乱序; */ 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 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} */ /** * 该方法判断index返回的正确性,若index正确则根据index新建List迭代器 */ 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) */ /** * 该方法新建一个List迭代器,索引值默认为0; */ 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 */ /** * ArrayList类的内部类,该类实现了Iterator接口; * 该内部类为基类 */ // 迭代器三大方法 : // hasNext 还有没有值可以迭代 // next 如果有值可以迭代, 迭代的值是多少 // remove 删除当前迭代的值 private class Itr implements Iterator<E> { // 迭代过程中,下一个元素的位置,默认从 0 开始 int cursor; // index of next element to return // 新增场景 : 表示上一次迭代过程中, 索引的位置; 删除场景为 -1 int lastRet = -1; // index of last element returned; -1 if no such // expectedModCount 表示迭代过程中, 期望的版本号; modCount 表示数组实际的版本号 int expectedModCount = modCount; // 当下一个元素的索引不为size时,表明存在下一个元素; public boolean hasNext() { //cursor 表示下一个元素的位置, size 表示实际大小, //如果两者相等, 说明已经没有元素可以迭代了, 如果不等, 说明还可以迭代 return cursor != size; } /** * checkForComodification()检查fast-fail机制; * 确保cursor,下个元素索引在ArrayList容量内并且该索引处存在元素值; * 取ArrayList中下个元素值并返回; */ // 主要功能 : // 1. 检验能不能继续迭代 // 2. 找到迭代的值并为下一次迭代做准备 (cursor + 1) @SuppressWarnings("unchecked") public E next() { // 迭代过程中, 判断版本号有无被修改, 有被修改, // 抛 ConcurrentModificationException 异常 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]; } /** * 该方法作用:删除列表迭代器刚刚访问的元素; * if (lastRet < 0):确保元素是刚刚访问的; * * checkForComodification()检查fast-fail机制; * * 方法内部通过ArrayList.this.remove(lastRet)对刚刚访问的元素进行删除操作; */ // 注意点 : // 1. lastRet = -1 的操作目的, 是防止重复删除操作 // 2. 删除元素成功, 数组当前 modCount 就会发生变化, // 这里会把 expectedModCount 重新赋值, 下次迭代时两者的值就会一致了 public void remove() { // 如果上一次操作时, 数组的位置已经小于 0 了, 说明数组已经被删除完了 if (lastRet < 0) throw new IllegalStateException(); // 迭代过程中, 判断版本号有无被修改, 有被修改, // 则抛 ConcurrentModificationException 异常 checkForComodification(); try { ArrayList.this.remove(lastRet); cursor = lastRet; // -1 表示元素已经被删除, 这里也防止重复删除 lastRet = -1; // 删除元素时 modCount 的值已经发生变化,在此赋值给 expectedModCount // 这样下次迭代时,两者的值是一致的了 expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } /** * 该方法遍历ArrayList中的元素,并对其中的元素执行相应的操作; */ @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(); } /** * 此处遍历elementData中的元素,并对元素执行consumer定义的操作 */ 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();:重新对modCount做检查以确保不在 * foreach循环中进行过对modCount存在影响的操作; */ checkForComodification(); } /** * 有两个线程(线程A,线程B),其中线程A负责遍历list、线程B修改list。 * 线程A在遍历list过程的某个时候(此时expectedModCount = modCount=N),线程启动, * 同时线程B增加一个元素,这是modCount的值发生改变(modCount + 1 = N + 1)。 * 线程A继续遍历执行next方法时, * 通告checkForComodification方法发现expectedModCount = N, * 而modCount = N + 1,两者不等, * 这时就抛出ConcurrentModificationException 异常,从而产生fail-fast机制。 * * modCount != expectedModCount时,抛出ConcurrentModificationException异常; */ // 版本号比较 final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } } /** * An optimized version of AbstractList.ListItr */ /** * 私有的内部类,该类继承Itr并实现了ListIterator接口 */ private class ListItr extends Itr implements ListIterator<E> { //构造方法 ListItr(int index) { super(); cursor = index; } //判断List是否存在前一个元素; public boolean hasPrevious() { return cursor != 0; } //获取List的下一个索引 public int nextIndex() { return cursor; } //获取List中的前一个索引 public int previousIndex() { return cursor - 1; } /** * 获取List中的前一个元素 * checkForComodification();:检查fast-fail机制; */ @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]; } /** * 该方法对刚刚访问的元素重新赋值; * if (lastRet < 0):确保元素是刚刚访问的; * checkForComodification();:检查fast-fail机制; */ public void set(E e) { if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { ArrayList.this.set(lastRet, e); } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } /** * 该方法在迭代器的下一个索引处添加元素; * checkForComodification();:检查fast-fail机制; */ 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} */ /** * 该方法用于返回子List; */ public List<E> subList(int fromIndex, int toIndex) { subListRangeCheck(fromIndex, toIndex, size); return new SubList(this, 0, fromIndex, toIndex); } /** * 该方法检查子List的索引是否正确; */ 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 + ")"); } /** * 私有内部类,该类继承AbstractList并实现了RandomAccess接口 * 内部类可以使用外部类中的方法; * * RandomAccess接口说明: * RandomAccess接口是一个标志接口 * 只要List集合实现这个接口,就能支持快速随机访问 * RandomAccess接口这个空架子的存在,是为了能够更好地判断集合是否ArrayList或者LinkedList, * 从而能够更好选择更优的遍历方式,提高性能 */ private class SubList extends AbstractList<E> implements RandomAccess { private final AbstractList<E> parent; private final int parentOffset; private final int offset; int size; /** * SubList构造方法; * SubList是在父类的基础上创建的,与父类共用一个内存空间; */ 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; } /** * 该方法用于在SubSet指定的索引处,设置元素的值; */ 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; } /** * 该方法用于获取SubSet指定的索引处元素的值; */ public E get(int index) { rangeCheck(index); checkForComodification(); return ArrayList.this.elementData(offset + index); } /** * 该方法返回SubList的大小; * 此处的this指的是SubList类; */ public int size() { checkForComodification(); return this.size; } /** * 该方法在SubList指定索引处添加元素; * parent.add(parentOffset + index, e);:SubList与parent共用一段内存空间 */ public void add(int index, E e) { rangeCheckForAdd(index); checkForComodification(); parent.add(parentOffset + index, e); this.modCount = parent.modCount; this.size++; } /** * 该方法删除SubList指定索引处的元素; * parent.remove(parentOffset + index);:SubList与parent共用一段内存空间 */ public E remove(int index) { rangeCheck(index); checkForComodification(); E result = parent.remove(parentOffset + index); this.modCount = parent.modCount; this.size--; return result; } /** * 该方法删除SubList指定索引范围内的元素; * parent.removeRange(parentOffset + fromIndex, parentOffset + toIndex); * :SubList与parent共用一段内存空间 */ protected void removeRange(int fromIndex, int toIndex) { checkForComodification(); parent.removeRange(parentOffset + fromIndex, parentOffset + toIndex); this.modCount = parent.modCount; this.size -= toIndex - fromIndex; } /** * 该方法在SubList的尾部添加集合元素; */ public boolean addAll(Collection<? extends E> c) { return addAll(this.size, c); } /** * 该方法在SubList的指定索引处添加集合元素; * parent.addAll(parentOffset + index, c);:SubList与parent共用一段内存空间 */ 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(); } /** * 该方法返回一个迭代器对象,迭代器在入参index的基础上创建; */ public ListIterator<E> listIterator(final int index) { checkForComodification(); rangeCheckForAdd(index); //this:SubList final int offset = this.offset; /** * ListIterator<E>(){}:匿名内部类 * return 返回了该匿名内部类的实例; */ return new ListIterator<E>() { int cursor = index; int lastRet = -1; int expectedModCount = ArrayList.this.modCount; public boolean hasNext() { return cursor != SubList.this.size; } //迭代器获取SubList的下一个元素; @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)]; } //迭代器判断SubList是否存在前一个元素; public boolean hasPrevious() { return cursor != 0; } //迭代器获取SubList的上一个元素; @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)]; } //迭代器遍历SubList的所有元素并执行相关的操作 @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(); } /** * 此处遍历elementData中的元素,并对元素执行consumer定义的操作 */ 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(); * :重新对modCount做检查以确保不在foreach循环中进行过对modCount存在影响的操作; */ 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(); } } //迭代器用于对刚刚访问的元素设置值; //ArrayList.this.set(offset + lastRet, e); //:SubList中的set方法需要提供index入参; 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(); } } //迭代器检查fast-fail规则 final void checkForComodification() { if (expectedModCount != ArrayList.this.modCount) throw new ConcurrentModificationException(); } }; } //SubList类的subList方法,用于返回SubList的SubList,即返回子序列的子序列; public List<E> subList(int fromIndex, int toIndex) { subListRangeCheck(fromIndex, toIndex, size); return new SubList(this, offset, fromIndex, toIndex); } //对SubList进行范围检查; private void rangeCheck(int index) { if (index < 0 || index >= this.size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } //对SubList进行范围检查,以便添加元素; private void rangeCheckForAdd(int index) { if (index < 0 || index > this.size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } //构建SubList的异常警告信息; private String outOfBoundsMsg(int index) { return "Index: "+index+", Size: "+this.size; } //SubList的fast-fail规则; private void checkForComodification() { if (ArrayList.this.modCount != this.modCount) throw new ConcurrentModificationException(); } /** * 该方法创建ArrayListSpliterator实例 * Spliterator是一个可分割迭代器(splitable iterator) * Spliterator就是为了并行遍历元素而设计的一个迭代器 */ public Spliterator<E> spliterator() { checkForComodification(); return new ArrayListSpliterator<E>(ArrayList.this, offset, offset + this.size, this.modCount); } } /** * 遍历SubList中的元素并对其执行相关的操作 * 操作不能改变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 */ //返回ArrayListSpliterator迭代器,用于并发迭代处理 @Override public Spliterator<E> spliterator() { return new ArrayListSpliterator<>(this, 0, -1, 0); } /** * static final: * static修饰的属性强调它们只有一个; * final修饰的属性表明是一个常数(创建后不能被修改); * static final修饰的属性表示一旦给值,就不可修改,并且可以通过类名访问; * * ArrayListSpliterator内部类,基于索引二分,迟加载的可分割迭代器,实现了Spliterator接口; */ /** 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 //当前List的最后一个索引值 private int fence; // -1 until used; then one past last index //修改次数,用于fast-fail规则 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; } //获取fence,初始化为list的size; 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; } /** * 对任务分割,返回一个新的Spliterator迭代器 * ArrayListSpliterator: * 采用二分的分割方式,返回lo--mid区间的Spliterator迭代器 */ 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); } /** * 获取Spliterator迭代器区间,并对区间内的元素执行相应的操作; */ 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; } /** * 对Spliterator迭代器区间中的元素执行相关操作; */ 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) { //初始化时的情况,初始化时fence为list的size; 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); } //判断fast-fail规则; 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; } } /** * Predicate:判断输入的对象是否符合某个条件 */ @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; /** * Bitset类创建一种特殊类型的数组来保存位值 */ 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)) { //若element满足相应的条件,则removeSet相应的位置位,removeCount加1; 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++) { //返回下一个清除位的索引,即BitSet中未置位的索引对应需要保留元素 i = removeSet.nextClearBit(i); elementData[j] = elementData[i]; } //对删除元素后对应的索引位置处的元素清空,赋值为NULL; for (int k=newSize; k < size; k++) { elementData[k] = null; // Let gc do its work } //更新List的size; this.size = newSize; //检查fast-fail规则 if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } //该方法对list进行了改动,因此需要修改modCount; modCount++; } return anyToRemove; } /** * 该方法使用UnaryOperator定义的方法修改List中的元素值; * * UnaryOperator:一元运算,接受一个T类型参数,输出一个与入参一模一样的值 */ @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,对elementData中的元素执行operator相关的操作, //并重新赋值到list原来索引处; elementData[i] = operator.apply((E) elementData[i]); } //检验fast-fail规则; if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } //改动了list,更新modCount; modCount++; } /** * 按照Comparator定义的规则对list进行排序; * * Comparator: * 按指定的Comparator规则对List排序; */ @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++; }}
致谢
本博客为博主的学习实践总结,并参考了众多博主的博文,在此表示感谢,博主若有不足之处,请批评指正。
发表评论
最新留言
能坚持,总会有不一样的收获!
[***.219.124.196]2025年04月10日 06时26分03秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
SQL函数返回表的写法
2021-05-09
delete对象时会自动调用类的析构函数
2021-05-09
C++ 子类对象直接赋值给父类对象可行,反过来不行
2021-05-09
linux下同一个动态库名为何辣么多的.so文件
2021-05-09
SQL联表的方式(逗号, Left Join, Right Join)
2021-05-09
牛客网输入输出举例
2021-05-09
字符串初始化时的注意点
2021-05-09
软考相关试题
2021-05-09
顺序表的操作
2021-05-09
常量表达式
2021-05-09
POD类型
2021-05-09
const与常量,傻傻分不清楚~
2021-05-09
Head First设计模式——迭代器模式
2021-05-09
MongoDB版本及存储引擎区别
2021-05-09
shell echo单行和多行文字定向写入到文件中
2021-05-09
AtCoder Beginner Contest 100 题解
2021-05-09
【数据结构】可持久化线段树初步
2021-05-09
Java高性能编程之CAS与ABA及解决方法
2021-05-09
从BIO到Netty的演变
2021-05-09
《算法导论》第二章笔记
2021-05-09