ArrayList 源码学习
一、了解 ArrayList
1.1 ArrayList 概述
引用百度百科的:
ArrayList 就是动态数组,用 MSDN 中的说法,就是 Array 的复杂版本,它提供了动态的增加和减少元素,实现了 Collection 和 List 接口,灵活的设置数组的大小等好处
1.2 ArrayList 定义
从定义可以看出:
- ArrayList 是 List 接口的大小可变数组的实现;
- ArrayList 实现了所有可选列表操作,并允许 null 元素;
- ArrayList 不断添加元素,容量也会自动增长;
- ArrayList 是不同步的,线程不安全的;
- ArrayList 的 iterator 和 listIterator 方法返回的迭代器是 fail-fast。
1.3 ArrayList 的数据结构
底层的数据结构就是数组,数组元素类型为 Object 类型,即可以存放所有类型数据。对 ArrayList 类的实例的所有操作底层都是基于数组的。
二、ArrayList 源码分析
2.1 ArrayList 继承结构和层次关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1lVkvwq5-1601967575238)(G:/noteImage/image-20201006093520760.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ig84FqSu-1601967575243)(G:/noteImage/image-20201006093539694.png)]
ArrayList 的继承结构:
ArrayList extends AbstractList
AbstractList extends AbstractCollection
由继承关系和层次关系可以看出:
- ArrayList :说明 ArrayList 支持泛型;
- 实现 RandomAccess 接口:表明 ArrayList 支持快速随机访问。什么是快速随机访问:可以通过元素的序号快速获取元素对象;
- 实现了 Cloneable 接口:可以使用 Object.clone() 方法了;
- java.io.Serializable:表明这个类可以被序列化。
2.2 ArrayList 类的常用属性
/**
* 序列号也就是版本号
*/
private static final long serialVersionUID = 8683452581122892189L;
/**
* Default initial capacity.
* 默认容量
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* Shared empty array instance used for empty instances.
* 空对象数组
* 当用户指定该 ArrayList 容量为 0 时,返回该空数组
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
* Shared empty array instance used for default sized empty instances. We
* distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
* first element is added.
* 默认空对象数组
* 用于默认大小的空实例的共享空数组实例。
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer. Any
* empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
* will be expanded to DEFAULT_CAPACITY when the first element is added.
* 元素数组。ArrayList 是基于数组实现的,用该数组保存数据,ArrayList 的容量就是该数组的长度
* 值为 elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA 的空 ArrayList 将在添加
* 第一个元素时扩容为 DEFAULT_CAPACITY
*/
transient Object[] elementData; // non-private to simplify nested class access
/**
* The size of the ArrayList (the number of elements it contains).
*
* @serial ArrayList 实际存储的数据容量,默认为 0
*/
private int size;
2.3 ArrayList 类的构造方法
ArrayList 提供了三种构造方法:
/**
* Constructs an empty list with the specified initial capacity.
* 创建一个有初始容量的、空的 ArrayList
*
* @param initialCapacity the initial capacity of the list list 的初始容量
* @throws IllegalArgumentException if the specified initial capacity
* is negative
* 如果初始容量值非法时(小于0)抛出异常
*/
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
// 将自定义的初始容量大小当成初始化 elementData 的大小
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
// 初始容量等于0,使用默认空对象数组
this.elementData = EMPTY_ELEMENTDATA;
} else {
// 如果初始容量小于0,则报非法数据异常
throw new IllegalArgumentException("Illegal Capacity: " +
initialCapacity);
}
}
/**
* Constructs an empty list with an initial capacity of ten.
* 构造一个初始容量为 10 的空的 list
* 无参构造函数
* 创建一个空的 ArrayList ,此时其内数组缓存区 elementData = {},长度为 0
* 当元素被第一次添加时,扩容至默认容量 10
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
/**
* Constructs a list containing the elements of the specified
* collection, in the order they are returned by the collection's
* iterator.
* 创建一个包含 Collection 的 ArrayList
*
* @param c the collection whose elements are to be placed into this list
* 要放入 ArrayList 中的集合,其内元素将会全部添加到新建的 ArrayList 实例中
* @throws NullPointerException if the specified collection is null 当参数 c 为 null 时抛出异常
*/
public ArrayList(Collection<? extends E> c) {
// 将集合转化成 Object 数组
elementData = c.toArray();
// 将转化后的 Object 数组的长度赋值给 ArrayList 的 size,闭关判断是否为 0
if ((size = elementData.length) != 0) {
// defend against c.toArray (incorrectly) not returning Object[]
// c.toArray 可能不会返回 Object 数组,详情请参见下面这个链接
// (see e.g. https://bugs.openjdk.java.net/browse/JDK-6260652)
if (elementData.getClass() != Object[].class)
// 若 c.toArray 返回的数组类型不是 Object[],使用 Arrays.copyOf来构建一个大小为 size 的 Object[] 数组
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
// 替换空数组
this.elementData = EMPTY_ELEMENTDATA;
}
}
ArrayList 的构造方法就是初始化内部的数组,也就是用来存储数据的容器。
2.4 ArrayList 类的常用方法
2.4.1 get() 方法
/**
* Returns the element at the specified position in this list.
* 返回在 ArrayList 中指定位置上的元素
* @param index index of the element to return 下标为 index 的元素
* @return the element at the specified position in this list
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E get(int index) {
// 检查是否越界
Objects.checkIndex(index, size);
return elementData(index);
}
/**
* 返回索引为 index 的元素:数组的随机访问
* 默认包访问权限
* @param index
* @return
*/
@SuppressWarnings("unchecked")
E elementData(int index) {
return (E) elementData[index];
}
get() 方法很简单,因为底层使用数组结构的,首先判断传过来的下标是否越界,使用的是 Objects 里面的方法判断;
然后直接通过数组的下标找到元素并返回。
2.4.2 set() 方法
/**
* Replaces the element at the specified position in this list with
* the specified element.
* 将 ArrayList 中指定位置的元素替换为指定的元素
* @param index index of the element to replace 索引值
* @param element element to be stored at the specified position 指定的元素
* @return the element previously at the specified position 替换前指定位置的元素
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E set(int index, E element) {
// 越界检查
Objects.checkIndex(index, size);
// 获取指定位置的元素
E oldValue = elementData(index);
// 将指定元素替换到指定的位置上
elementData[index] = element;
// 返回旧数据
return oldValue;
}
2.4.3 add() 方法
-
public boolean add(E e) // 一个参数的
/** * Appends the specified element to the end of this list. * 增加指定的元素到 ArrayList 的最后位置 * @param e element to be appended to this list * 要添加到 ArrayList 的元素 * @return {@code true} (as specified by {@link Collection#add}) */ public boolean add(E e) { modCount++; add(e, elementData, size); return true; } /** * This helper method split out from add(E) to keep method * bytecode size under 35 (the -XX:MaxInlineSize default value), * which helps when add(E) is called in a C1-compiled loop. * * 这个 helper 方法从 add(E) 中分离出来, * 使 method bytecode 的大小保持在 35 以下(-XX:MaxInlineSize默认值), * 这有助于在 c1 编译循环中调用 add(E)。 */ private void add(E e, Object[] elementData, int s) { // ArrayList 的实际容量等于数组的长度,就需要进行扩容操作 if (s == elementData.length) elementData = grow(); // 将指定的元素添加到 ArrayList 的最后位置 elementData[s] = e; // 大小+1 size = s + 1; } /** * Increases the capacity to ensure that it can hold at least the * number of elements specified by the minimum capacity argument. * 以新的容量创建一个数组,然后将原数组的数据复制到新创建的数组中 * 增加容量以确保它至少可以容纳参数指定的元素数量 * @param minCapacity the desired minimum capacity 指定的最小容量 * @throws OutOfMemoryError if minCapacity is less than zero 如果容量小于0 */ private Object[] grow(int minCapacity) { return elementData = Arrays.copyOf(elementData, newCapacity(minCapacity)); } private Object[] grow() { return grow(size + 1); } /** * Returns a capacity at least as large as the given minimum capacity. * Returns the current capacity increased by 50% if that suffices. * Will not return a capacity greater than MAX_ARRAY_SIZE unless * the given minimum capacity is greater than MAX_ARRAY_SIZE. * 真正的将容量扩容 * 返回的容量至少与给定的最小容量一样大。 * 如果足够的话,当前的容量增加了 50%。 * 不会返回大于 MAX_ARRAY_SIZE 的容量,除非给定的最小容量大于 MAX_ARRAY_SIZE * @param minCapacity the desired minimum capacity * @throws OutOfMemoryError if minCapacity is less than zero 如果容量小于0 */ private int newCapacity(int minCapacity) { // overflow-conscious code // 防止溢出代码 int oldCapacity = elementData.length; // 运算符 >> 是带符号的右移,比如 oldCapacity = 10,则 10 + (10 >> 1) = 15 int newCapacity = oldCapacity + (oldCapacity >> 1); // 如果新的容量小于等于指定的最小容量 if (newCapacity - minCapacity <= 0) { // 如果当前数组是默认的空数组对象 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) // 返回默认容量和指定的最小容量中的最大值 return Math.max(DEFAULT_CAPACITY, minCapacity); if (minCapacity < 0) // overflow,指定的最小容量小于0,抛出异常 throw new OutOfMemoryError(); // 返回指定的最小容量 return minCapacity; } // 新的容量大于指定的最小容量 // 如果新容量小于等于最大存储容量,返回新容量,否则进行大容量分配 return (newCapacity - MAX_ARRAY_SIZE <= 0) ? newCapacity : hugeCapacity(minCapacity); }
执行流程:
-
public void add(int index, E element)// 两个参数的
/** * Inserts the specified element at the specified position in this * list. Shifts the element currently at that position (if any) and * any subsequent elements to the right (adds one to their indices). * 在这个 ArrayList 的指定位置插入指定的元素。 * 将元素当前的位置(如果有的话)和后续的元素向右移动(在它们的索引中添加一个)。 * @param index index at which the specified element is to be inserted * 要插入指定元素的索引 * @param element element to be inserted 要插入的元素 * @throws IndexOutOfBoundsException {@inheritDoc} */ public void add(int index, E element) { // 判断角标是否越界 rangeCheckForAdd(index); modCount++; final int s; Object[] elementData; // ArrayList 的实际容量等于数组的长度,就需要进行扩容操作 // 将 size 的大小赋值给 s,将这个对象的数组赋值给 elementData if ((s = size) == (elementData = this.elementData).length) elementData = grow(); // 第一个是要复制的数组,第二个是从要复制的数组的第几个开始, // 第三个是复制到那,四个是复制到的数组第几个开始,最后一个是复制长度 // 意思就是将 index 之后的元素包括 index 复制到 index+1 之后 System.arraycopy(elementData, index, elementData, index + 1, s - index); // 将指定的元素插入到指定的位置 elementData[index] = element; // 实际大小 +1 size = s + 1; } /** * A version of rangeCheck used by add and addAll. * 添加时检查索引是否越界 */ private void rangeCheckForAdd(int index) { if (index > size || index < 0) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); }
执行流程:和带一个参数的 add() 方法一样,就是最后添加元素不是添加到 ArrayList 的最后位置,而是添加到指定位置。
2.4.4 remove() 方法
-
通过索引删除指定位置的元素
/** * Removes the element at the specified position in this list. * Shifts any subsequent elements to the left (subtracts one from their * indices). * 移除 ArrayList 中指定位置的元素。将后面的元素向左移动(从它们的下标中减去1) * @param index the index of the element to be removed 指定的位置 * @return the element that was removed from the list 被移除的元素 * @throws IndexOutOfBoundsException {@inheritDoc} */ public E remove(int index) { // 判断下标是否越界 Objects.checkIndex(index, size); final Object[] es = elementData; @SuppressWarnings("unchecked") E oldValue = (E) es[index]; // 真正实现移除的私有方法 fastRemove(es, index); return oldValue; } /** * Private remove method that skips bounds checking and does not * return the value removed. * 跳过边界检查且不返回已删除值的私有移除方法。 */ private void fastRemove(Object[] es, int i) { modCount++; final int newSize; if ((newSize = size - 1) > i)// 要移动的长度 // 将 i+1 及其后面的元素复制到 i 及其后面的下标上 System.arraycopy(es, i + 1, es, i, newSize - i); // 将最后一个位置置为空 es[size = newSize] = null; }
执行流程:
- 判断数组下标是否越界;
- 修改次数自增(modCount 是用来检测 fail-fast 的标志);
- 计算要移动的长度;
- 移动元素,也就是复制;
- 将最后一个位置置空,也就是 size 的位置为 null;
- 返回被删除的元素。
-
通过对象删除指定元素
/** * Removes the first occurrence of the specified element from this list, * if it is present. If the list does not contain the element, it is * unchanged. More formally, removes the element with the lowest index * {@code i} such that * {@code Objects.equals(o, get(i))} * (if such an element exists). Returns {@code true} if this list * contained the specified element (or equivalently, if this list * changed as a result of the call). * 如果指定元素出现,移除这个 ArrayList 中第一次出现的元素。 * 如果 ArrayList 不包含这个元素,ArrayList 不会改变。 * @param o element to be removed from this list, if present 要删除的元素 * @return {@code true} if this list contained the specified element 如果包含指定的元素返回 true */ public boolean remove(Object o) { final Object[] es = elementData; final int size = this.size; int i = 0; found: { if (o == null) { for (; i < size; i++) if (es[i] == null) break found; } else { for (; i < size; i++) if (o.equals(es[i])) break found; } return false; } fastRemove(es, i); return true; }
-
removeRange(int fromIndex, int toIndex)
/** * Removes from this list all of the elements whose index is between * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive. * Shifts any succeeding elements to the left (reduces their index). * This call shortens the list by {@code (toIndex - fromIndex)} elements. * (If {@code toIndex==fromIndex}, this operation has no effect.) * 从 ArrayList 中移除索引在 fromIndex 和 toIndex 之间所有的元素 * 将所有元素向左移动(toIndex-fromIndex)个元素 * 如果 (toIndex==fromIndex)这个操作没有影响 * @throws IndexOutOfBoundsException if {@code fromIndex} or * {@code toIndex} is out of range * ({@code fromIndex < 0 || * toIndex > size() || * toIndex < fromIndex}) */ protected void removeRange(int fromIndex, int toIndex) { if (fromIndex > toIndex) { throw new IndexOutOfBoundsException( outOfBoundsMsg(fromIndex, toIndex)); } modCount++; shiftTailOverGap(elementData, fromIndex, toIndex); } /** * Erases the gap from lo to hi, by sliding down following elements. * 通过向下滑动以下元素来消除从lo到hi的间隙 */ private void shiftTailOverGap(Object[] es, int lo, int hi) { // size-hi 要移动的数量 System.arraycopy(es, hi, es, lo, size - hi); // 将失效元素置空 for (int to = size, i = (size -= hi - lo); i < to; i++) es[i] = null; }
-
removeAll(Collection<?> c)
/** * Removes from this list all of its elements that are contained in the * specified collection. * 从此 ArrayList 中删除指定的集合中包含的所有元素。 * @param c collection containing elements to be removed from this list * 要从 list 中删除的元素的集合 * @return {@code true} if this list changed as a result of the call * @throws ClassCastException if the class of an element of this list * is incompatible with the specified collection * (<a href="Collection.html#optional-restrictions">optional</a>) * @throws NullPointerException if this list contains a null element and the * specified collection does not permit null elements * (<a href="Collection.html#optional-restrictions">optional</a>), * or if the specified collection is null * @see Collection#contains(Object) */ public boolean removeAll(Collection<?> c) { return batchRemove(c, false, 0, size); } /** * 批处理移除 * @param c 要移除的集合 * @param complement 是否是补集 * 如果true:移除list中除了c集合中的所有元素 * 如果false:移除list中 c集合中的元素 * @param from * @param end * @return */ boolean batchRemove(Collection<?> c, boolean complement, final int from, final int end) { // 检查要移除的集合不为空 Objects.requireNonNull(c); final Object[] es = elementData; int r; // Optimize for initial run of survivors for (r = from; ; r++) { if (r == end) return false; if (c.contains(es[r]) != complement) break; } int w = r++; try { for (Object e; r < end; r++) if (c.contains(e = es[r]) == complement) es[w++] = e; } catch (Throwable ex) { // Preserve behavioral compatibility with AbstractCollection, // even if c.contains() throws. System.arraycopy(es, r, es, w, end - r); w += end - r; throw ex; } finally { modCount += end - w; shiftTailOverGap(es, w, end); } return true; }
-
retainAll(Collection<?> c)
public boolean retainAll(Collection<?> c) { return batchRemove(c, true, 0, size); }
2.4.5 indexOf() 和 lastIndexOf() 方法
/**
* Returns the index of the first occurrence of the specified element
* in this list, or -1 if this list does not contain the element.
* More formally, returns the lowest index {@code i} such that
* {@code Objects.equals(o, get(i))},
* or -1 if there is no such index.
*
* 返回 ArrayList 中指定元素的第一个匹配项的索引,如果 ArrayList 不包含该元素,返回 -1
* 更准确的说,返回最低索引 i ,以便 o.equals(es[i]),如果没有这样的索引,返回 -1
*/
public int indexOf(Object o) {
return indexOfRange(o, 0, size);
}
/**
* 顺序查找,返回元素的z最低索引值(最先出现的索引位置)
* @param o
* @param start
* @param end
* @return 存在 ? 最低索引值 : -1
*/
int indexOfRange(Object o, int start, int end) {
Object[] es = elementData;
if (o == null) {
for (int i = start; i < end; i++) {
if (es[i] == null) {
return i;
}
}
} else {
for (int i = start; i < end; i++) {
if (o.equals(es[i])) {
return i;
}
}
}
return -1;
}
/**
* Returns the index of the last occurrence of the specified element
* in this list, or -1 if this list does not contain the element.
* More formally, returns the highest index {@code i} such that
* {@code Objects.equals(o, get(i))},
* or -1 if there is no such index.
*
* 返回 ArrayList 中指定元素的最后一个匹配项的索引,如果 ArrayList 不包含该元素,返回 -1
* 更准确的说,返回最高索引 i ,以便 o.equals(es[i]),如果没有这样的索引,返回 -1
*/
public int lastIndexOf(Object o) {
return lastIndexOfRange(o, 0, size);
}
/**
* 逆序查找
* @param o
* @param start
* @param end
* @return 存在 ? 最高索引 : -1
*/
int lastIndexOfRange(Object o, int start, int end) {
Object[] es = elementData;
if (o == null) {
for (int i = end - 1; i >= start; i--) {
if (es[i] == null) {
return i;
}
}
} else {
for (int i = end - 1; i >= start; i--) {
if (o.equals(es[i])) {
return i;
}
}
}
return -1;
}
2.5 ArrayList 类的完整解读
package com.xiaoyu.util;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
/**
* Resizable-array implementation of the {@code List} interface. Implements
* all optional list operations, and permits all elements, including
* {@code null}. In addition to implementing the {@code List} interface,
* this class provides methods to manipulate the size of the array that is
* used internally to store the list. (This class is roughly equivalent to
* {@code Vector}, except that it is unsynchronized.)
*
* <p>The {@code size}, {@code isEmpty}, {@code get}, {@code set},
* {@code iterator}, and {@code listIterator} operations run in constant
* time. The {@code add} operation runs in <i>amortized constant time</i>,
* that is, adding n elements requires O(n) time. All of the other operations
* run in linear time (roughly speaking). The constant factor is low compared
* to that for the {@code LinkedList} implementation.
*
* <p>Each {@code ArrayList} instance has a <i>capacity</i>. The capacity is
* the size of the array used to store the elements in the list. It is always
* at least as large as the list size. As elements are added to an ArrayList,
* its capacity grows automatically. The details of the growth policy are not
* specified beyond the fact that adding an element has constant amortized
* time cost.
*
* <p>An application can increase the capacity of an {@code ArrayList} instance
* before adding a large number of elements using the {@code ensureCapacity}
* operation. This may reduce the amount of incremental reallocation.
*
* <p><strong>Note that this implementation is not synchronized.</strong>
* If multiple threads access an {@code ArrayList} instance concurrently,
* and at least one of the threads modifies the list structurally, it
* <i>must</i> be synchronized externally. (A structural modification is
* any operation that adds or deletes one or more elements, or explicitly
* resizes the backing array; merely setting the value of an element is not
* a structural modification.) This is typically accomplished by
* synchronizing on some object that naturally encapsulates the list.
* <p>
* If no such object exists, the list should be "wrapped" using the
* {@link Collections#synchronizedList Collections.synchronizedList}
* method. This is best done at creation time, to prevent accidental
* unsynchronized access to the list:<pre>
* List list = Collections.synchronizedList(new ArrayList(...));</pre>
*
* <p id="fail-fast">
* The iterators returned by this class's {@link #iterator() iterator} and
* {@link #listIterator(int) listIterator} methods are <em>fail-fast</em>:
* if the list is structurally modified at any time after the iterator is
* created, in any way except through the iterator's own
* {@link ListIterator#remove() remove} or
* {@link ListIterator#add(Object) add} methods, the iterator will throw a
* {@link ConcurrentModificationException}. Thus, in the face of
* concurrent modification, the iterator fails quickly and cleanly, rather
* than risking arbitrary, non-deterministic behavior at an undetermined
* time in the future.
*
* <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
* as it is, generally speaking, impossible to make any hard guarantees in the
* presence of unsynchronized concurrent modification. Fail-fast iterators
* throw {@code ConcurrentModificationException} on a best-effort basis.
* Therefore, it would be wrong to write a program that depended on this
* exception for its correctness: <i>the fail-fast behavior of iterators
* should be used only to detect bugs.</i>
*
* <p>This class is a member of the
* <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @param <E> the type of elements in this list
* @author Josh Bloch
* @author Neal Gafter
* @see Collection
* @see List
* @see LinkedList
* @see Vector
* @since 1.2
*/
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
/**
* 序列号也就是版本号
*/
private static final long serialVersionUID = 8683452581122892189L;
/**
* Default initial capacity.
* 默认容量
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* Shared empty array instance used for empty instances.
* 空对象数组
* 当用户指定该 ArrayList 容量为 0 时,返回该空数组
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
* Shared empty array instance used for default sized empty instances. We
* distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
* first element is added.
* 默认空对象数组
* 用于默认大小的空实例的共享空数组实例。
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer. Any
* empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
* will be expanded to DEFAULT_CAPACITY when the first element is added.
* 元素数组。ArrayList 是基于数组实现的,用该数组保存数据,ArrayList 的容量就是该数组的长度
* 值为 elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA 的空 ArrayList 将在添加
* 第一个元素时扩容为 DEFAULT_CAPACITY
*/
transient Object[] elementData; // non-private to simplify nested class access
/**
* The size of the ArrayList (the number of elements it contains).
*
* @serial ArrayList 实际存储的数据容量,默认为 0
*/
private int size;
/**
* Constructs an empty list with the specified initial capacity.
* 创建一个有初始容量的、空的 ArrayList
*
* @param initialCapacity the initial capacity of the list list 的初始容量
* @throws IllegalArgumentException if the specified initial capacity
* is negative
* 如果初始容量值非法时(小于0)抛出异常
*/
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
// 将自定义的初始容量大小当成初始化 elementData 的大小
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
// 初始容量等于0,使用默认空对象数组
this.elementData = EMPTY_ELEMENTDATA;
} else {
// 如果初始容量小于0,则报非法数据异常
throw new IllegalArgumentException("Illegal Capacity: " +
initialCapacity);
}
}
/**
* Constructs an empty list with an initial capacity of ten.
* 构造一个初始容量为 10 的空的 list
* 无参构造函数
* 创建一个空的 ArrayList ,此时其内数组缓存区 elementData = {},长度为 0
* 当元素被第一次添加时,扩容至默认容量 10
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
/**
* Constructs a list containing the elements of the specified
* collection, in the order they are returned by the collection's
* iterator.
* 创建一个包含 Collection 的 ArrayList
*
* @param c the collection whose elements are to be placed into this list
* 要放入 ArrayList 中的集合,其内元素将会全部添加到新建的 ArrayList 实例中
* @throws NullPointerException if the specified collection is null 当参数 c 为 null 时抛出异常
*/
public ArrayList(Collection<? extends E> c) {
// 将集合转化成 Object 数组
elementData = c.toArray();
// 将转化后的 Object 数组的长度赋值给 ArrayList 的 size,闭关判断是否为 0
if ((size = elementData.length) != 0) {
// defend against c.toArray (incorrectly) not returning Object[]
// c.toArray 可能不会返回 Object 数组,详情请参见下面这个链接
// (see e.g. https://bugs.openjdk.java.net/browse/JDK-6260652)
if (elementData.getClass() != Object[].class)
// 若 c.toArray 返回的数组类型不是 Object[],使用 Arrays.copyOf来构建一个大小为 size 的 Object[] 数组
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
// 替换空数组
this.elementData = EMPTY_ELEMENTDATA;
}
}
/**
* Trims the capacity of this {@code ArrayList} instance to be the
* list's current size. An application can use this operation to minimize
* the storage of an {@code ArrayList} instance.
* 将数组缓存区大小调整到实际 ArrayList 存储元素的大小,即 elementData = Arrays.copyOf(elementData,size)
* 这个方法由用户自己手动调用,以减少空间资源浪费的目的
*/
public void trimToSize() {
// modCount 是 AbstractList 的属性
// modCount有什么作用?
// 记录修改次数,
modCount++;
// 实际大小小于数组缓存区大小
if (size < elementData.length) {
// 这里执行的是elementData = ((size == 0) ? EMPTY_ELEMENTDATA : Arrays.copyOf(elementData, size))
// 调整数组缓存区 elementData 变为实际存储大小 Arrays.copyOf(elementData, size)
// 如果 size 为 0,实际存储为 EMPTY_ELEMENTDATA,如果有数据就是 Arrays.copyOf(elementData, size)
elementData = (size == 0)
? EMPTY_ELEMENTDATA
: Arrays.copyOf(elementData, size);
}
}
/**
* Increases the capacity of this {@code ArrayList} instance, if
* necessary, to ensure that it can hold at least the number of elements
* specified by the minimum capacity argument.
* 指定 ArrayList 的容量
* @param minCapacity the desired minimum capacity
* 指定的最小容量
*/
public void ensureCapacity(int minCapacity) {
// 如果最小容量大于数组缓存区当前的长度且
// (数组不等于默认空数组且用户指定的最小容量大于最小扩充容量)
if (minCapacity > elementData.length
&& !(elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
&& minCapacity <= DEFAULT_CAPACITY)) {
// 修改次数自增,这个变量主要是用来实现 fail-fast 机制的
modCount++;
// 进行扩容操作
grow(minCapacity);
}
}
/**
* The maximum size of array to allocate (unless necessary).
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*
* 数组缓存区最大存储容量,数组分配的最大大小
* 一些虚拟机(VM)在数组中保留一些数据(头字)
* 尝试分配较大的数组可能会导致 OutOfMemoryError:请求的数组大小超过 VM 限制
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
/**
* Increases the capacity to ensure that it can hold at least the
* number of elements specified by the minimum capacity argument.
* 以新的容量创建一个数组,然后将原数组的数据复制到新创建的数组中
* 增加容量以确保它至少可以容纳参数指定的元素数量
* @param minCapacity the desired minimum capacity 指定的最小容量
* @throws OutOfMemoryError if minCapacity is less than zero 如果容量小于0
*/
private Object[] grow(int minCapacity) {
return elementData = Arrays.copyOf(elementData,
newCapacity(minCapacity));
}
private Object[] grow() {
return grow(size + 1);
}
/**
* Returns a capacity at least as large as the given minimum capacity.
* Returns the current capacity increased by 50% if that suffices.
* Will not return a capacity greater than MAX_ARRAY_SIZE unless
* the given minimum capacity is greater than MAX_ARRAY_SIZE.
* 真正的将容量扩容
* 返回的容量至少与给定的最小容量一样大。
* 如果足够的话,当前的容量增加了 50%。
* 不会返回大于 MAX_ARRAY_SIZE 的容量,除非给定的最小容量大于 MAX_ARRAY_SIZE
* @param minCapacity the desired minimum capacity
* @throws OutOfMemoryError if minCapacity is less than zero 如果容量小于0
*/
private int newCapacity(int minCapacity) {
// overflow-conscious code
// 防止溢出代码
int oldCapacity = elementData.length;
// 运算符 >> 是带符号的右移,比如 oldCapacity = 10,则 10 + (10 >> 1) = 15
int newCapacity = oldCapacity + (oldCapacity >> 1);
// 如果新的容量小于等于指定的最小容量
if (newCapacity - minCapacity <= 0) {
// 如果当前数组是默认的空数组对象
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
// 返回默认容量和指定的最小容量中的最大值
return Math.max(DEFAULT_CAPACITY, minCapacity);
if (minCapacity < 0) // overflow,指定的最小容量小于0,抛出异常
throw new OutOfMemoryError();
// 返回指定的最小容量
return minCapacity;
}
// 新的容量大于指定的最小容量
// 如果新容量小于等于最大存储容量,返回新容量,否则进行大容量分配
return (newCapacity - MAX_ARRAY_SIZE <= 0)
? newCapacity
: hugeCapacity(minCapacity);
}
/**
* 私有方法:大容量分配,最大分配:Integer.MAX_VALUE
* @param minCapacity
* @return
*/
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE)
? Integer.MAX_VALUE
: MAX_ARRAY_SIZE;
}
/**
* Returns the number of elements in this list.
* 返回 ArrayList 中元素的数量
* @return the number of elements in this list
*/
public int size() {
return size;
}
/**
* Returns {@code true} if this list contains no elements.
* 如果 ArrayList 为空,返回 true
* @return {@code true} if this list contains no elements
*/
public boolean isEmpty() {
return size == 0;
}
/**
* Returns {@code true} if this list contains the specified element.
* More formally, returns {@code true} if and only if this list contains
* at least one element {@code e} such that
* {@code Objects.equals(o, e)}.
* 如果 ArrayList 中包含指定元素,返回 true
* 更准确的说,当且仅当 ArrayList 中包含至少一个元素 o 时返回 true
* @param o element whose presence in this list is to be tested
* @return {@code true} if this list contains the specified element
*/
public boolean contains(Object o) {
// 根据 indexOf() 的值(索引值)来判断,大于等于 0 就包含
// 等于 0 的情况不能漏掉,因为数组的下标从 0 开始
return indexOf(o) >= 0;
}
/**
* Returns the index of the first occurrence of the specified element
* in this list, or -1 if this list does not contain the element.
* More formally, returns the lowest index {@code i} such that
* {@code Objects.equals(o, get(i))},
* or -1 if there is no such index.
*
* 返回 ArrayList 中指定元素的第一个匹配项的索引,如果 ArrayList 不包含该元素,返回 -1
* 更准确的说,返回最低索引 i ,以便 o.equals(es[i]),如果没有这样的索引,返回 -1
*/
public int indexOf(Object o) {
return indexOfRange(o, 0, size);
}
/**
* 顺序查找,返回元素的z最低索引值(最先出现的索引位置)
* @param o
* @param start
* @param end
* @return 存在 ? 最低索引值 : -1
*/
int indexOfRange(Object o, int start, int end) {
Object[] es = elementData;
if (o == null) {
for (int i = start; i < end; i++) {
if (es[i] == null) {
return i;
}
}
} else {
for (int i = start; i < end; i++) {
if (o.equals(es[i])) {
return i;
}
}
}
return -1;
}
/**
* Returns the index of the last occurrence of the specified element
* in this list, or -1 if this list does not contain the element.
* More formally, returns the highest index {@code i} such that
* {@code Objects.equals(o, get(i))},
* or -1 if there is no such index.
*
* 返回 ArrayList 中指定元素的最后一个匹配项的索引,如果 ArrayList 不包含该元素,返回 -1
* 更准确的说,返回最高索引 i ,以便 o.equals(es[i]),如果没有这样的索引,返回 -1
*/
public int lastIndexOf(Object o) {
return lastIndexOfRange(o, 0, size);
}
/**
* 逆序查找
* @param o
* @param start
* @param end
* @return 存在 ? 最高索引 : -1
*/
int lastIndexOfRange(Object o, int start, int end) {
Object[] es = elementData;
if (o == null) {
for (int i = end - 1; i >= start; i--) {
if (es[i] == null) {
return i;
}
}
} else {
for (int i = end - 1; i >= start; i--) {
if (o.equals(es[i])) {
return i;
}
}
}
return -1;
}
/**
* Returns a shallow copy of this {@code ArrayList} instance. (The
* elements themselves are not copied.)
* 返回这个{@code ArrayList}实例的浅拷贝。(元素本身不会被复制。)
* @return a clone of this {@code ArrayList} instance 一个克隆的 ArrayList 实例(深度复制的结果)
*/
public Object clone() {
try {
// Object 的克隆方法:会复制对象本身及其内所有基本类型成员和 String 类型成员,但不会复制对象成员和引用对象
ArrayList<?> v = (ArrayList<?>) super.clone();
// 对需要进行复制的引用变量进行独立的拷贝:将存储的元素移到新的 ArrayList 中
v.elementData = Arrays.copyOf(elementData, size);
v.modCount = 0;
return v;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
// 这不应该发生,因为我们是可克隆的
throw new InternalError(e);
}
}
/**
* Returns an array containing all of the elements in this list
* in proper sequence (from first to last element).
*
* <p>The returned array will be "safe" in that no references to it are
* maintained by this list. (In other words, this method must allocate
* a new array). The caller is thus free to modify the returned array.
*
* <p>This method acts as bridge between array-based and collection-based
* APIs.
*
* @return an array containing all of the elements in this list in
* proper sequence
*
* 返回一个Object数组,这个数组包含 ArrayList 中的所有元素,并且顺序一致(从第一个元素到最后一个元素)
* 对返回的数组进行操作时安全的,不会影响 ArrayList,也就是说这个方法必须分配一个新的数组,调用中可以自由的修改返回的数组
* 这个方法充当基于数组和基于集合 api 之间的桥梁
*/
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}
/**
* Returns an array containing all of the elements in this list in proper
* sequence (from first to last element); the runtime type of the returned
* array is that of the specified array. If the list fits in the
* specified array, it is returned therein. Otherwise, a new array is
* allocated with the runtime type of the specified array and the size of
* this list.
*
* <p>If the list fits in the specified array with room to spare
* (i.e., the array has more elements than the list), the element in
* the array immediately following the end of the collection is set to
* {@code null}. (This is useful in determining the length of the
* list <i>only</i> if the caller knows that the list does not contain
* any null elements.)
* 返回一个包含 ArrayList 中所有元素的数组(从第一个元素到最后一个元素)
* 返回数组的运行时类型是指定的数组类型,如果 ArrayList 与数组匹配,则返回 ArrayList;否则
* 将为新数组分配指定数组的运行时类型和这个 ArrayList 的大小
* @param a the array into which the elements of the list are to
* be stored, if it is big enough; otherwise, a new array of the
* same runtime type is allocated for this purpose.
* 需要存储 list 中元素的数组
* 若 a.length >= list.size,则将 list 中的元素按顺序存入 a 中,
* 然后 a[list.size] = null, a[list.size + 1] 及其后的元素依旧是 a 的元素;
* 否则,将返回包含list 所有元素且数组长度等于 list 中元素个数的数组
* @return an array containing the elements of the list
* @throws ArrayStoreException if the runtime type of the specified array
* is not a supertype of the runtime type of every element in
* this list
* 当 a.getClass() != list 中存储元素的类型时
* @throws NullPointerException if the specified array is null 当 a 为 null 时
*/
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
// 如果数组 a 的大小小于 ArrayList 的元素个数,则新建一个 T[] 数组
// 数组大小时 ArrayList 的元素个数,并把 ArrayList 全部拷贝到新的数组中
if (a.length < size)
// Make a new array of a's runtime type, but my contents:
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
// 如果数组 a 的大小大于 ArrayList 的元素个数,将 ArrayList 中的元素全部拷贝到数组 a 中
System.arraycopy(elementData, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
// Positional Access Operations 位置访问操作
/**
* 返回索引为 index 的元素:数组的随机访问
* 默认包访问权限
* @param index
* @return
*/
@SuppressWarnings("unchecked")
E elementData(int index) {
return (E) elementData[index];
}
@SuppressWarnings("unchecked")
static <E> E elementAt(Object[] es, int index) {
return (E) es[index];
}
/**
* Returns the element at the specified position in this list.
* 返回在 ArrayList 中指定位置上的元素
* @param index index of the element to return 下标为 index 的元素
* @return the element at the specified position in this list
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E get(int index) {
// 检查是否越界
Objects.checkIndex(index, size);
return elementData(index);
}
/**
* Replaces the element at the specified position in this list with
* the specified element.
* 将 ArrayList 中指定位置的元素替换为指定的元素
* @param index index of the element to replace 索引值
* @param element element to be stored at the specified position 指定的元素
* @return the element previously at the specified position 替换前指定位置的元素
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E set(int index, E element) {
// 越界检查
Objects.checkIndex(index, size);
// 获取指定位置的元素
E oldValue = elementData(index);
// 将指定元素替换到指定的位置上
elementData[index] = element;
// 返回旧数据
return oldValue;
}
/**
* This helper method split out from add(E) to keep method
* bytecode size under 35 (the -XX:MaxInlineSize default value),
* which helps when add(E) is called in a C1-compiled loop.
*
* 这个 helper 方法从 add(E) 中分离出来,
* 使 method bytecode 的大小保持在 35 以下(-XX:MaxInlineSize默认值),
* 这有助于在 c1 编译循环中调用 add(E)。
*/
private void add(E e, Object[] elementData, int s) {
// ArrayList 的实际容量等于数组的长度,就需要进行扩容操作
if (s == elementData.length)
elementData = grow();
// 将指定的元素添加到 ArrayList 的最后位置
elementData[s] = e;
// 大小+1
size = s + 1;
}
/**
* Appends the specified element to the end of this list.
* 增加指定的元素到 ArrayList 的最后位置
* @param e element to be appended to this list
* 要添加到 ArrayList 的元素
* @return {@code true} (as specified by {@link Collection#add})
*/
public boolean add(E e) {
modCount++;
add(e, elementData, size);
return true;
}
/**
* Inserts the specified element at the specified position in this
* list. Shifts the element currently at that position (if any) and
* any subsequent elements to the right (adds one to their indices).
* 在这个 ArrayList 的指定位置插入指定的元素。
* 将元素当前的位置(如果有的话)和后续的元素向右移动(在它们的索引中添加一个)。
* @param index index at which the specified element is to be inserted
* 要插入指定元素的索引
* @param element element to be inserted 要插入的元素
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public void add(int index, E element) {
// 判断角标是否越界
rangeCheckForAdd(index);
modCount++;
final int s;
Object[] elementData;
// ArrayList 的实际容量等于数组的长度,就需要进行扩容操作
// 将 size 的大小赋值给 s,将这个对象的数组赋值给 elementData
if ((s = size) == (elementData = this.elementData).length)
elementData = grow();
// 第一个是要复制的数组,第二个是从要复制的数组的第几个开始,
// 第三个是复制到那,四个是复制到的数组第几个开始,最后一个是复制长度
// 意思就是将 index 之后的元素包括 index 复制到 index+1 之后
System.arraycopy(elementData, index,
elementData, index + 1,
s - index);
// 将指定的元素插入到指定的位置
elementData[index] = element;
// 实际大小 +1
size = s + 1;
}
/**
* Removes the element at the specified position in this list.
* Shifts any subsequent elements to the left (subtracts one from their
* indices).
* 移除 ArrayList 中指定位置的元素。将后面的元素向左移动(从它们的下标中减去1)
* @param index the index of the element to be removed 指定的位置
* @return the element that was removed from the list 被移除的元素
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E remove(int index) {
// 判断下标是否越界
Objects.checkIndex(index, size);
final Object[] es = elementData;
@SuppressWarnings("unchecked") E oldValue = (E) es[index];
// 真正实现移除的私有方法
fastRemove(es, index);
return oldValue;
}
/**
* {@inheritDoc}
*/
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof List)) {
return false;
}
final int expectedModCount = modCount;
// ArrayList can be subclassed and given arbitrary behavior, but we can
// still deal with the common case where o is ArrayList precisely
boolean equal = (o.getClass() == ArrayList.class)
? equalsArrayList((ArrayList<?>) o)
: equalsRange((List<?>) o, 0, size);
checkForComodification(expectedModCount);
return equal;
}
boolean equalsRange(List<?> other, int from, int to) {
final Object[] es = elementData;
if (to > es.length) {
throw new ConcurrentModificationException();
}
var oit = other.iterator();
for (; from < to; from++) {
if (!oit.hasNext() || !Objects.equals(es[from], oit.next())) {
return false;
}
}
return !oit.hasNext();
}
private boolean equalsArrayList(ArrayList<?> other) {
final int otherModCount = other.modCount;
final int s = size;
boolean equal;
if (equal = (s == other.size)) {
final Object[] otherEs = other.elementData;
final Object[] es = elementData;
if (s > es.length || s > otherEs.length) {
throw new ConcurrentModificationException();
}
for (int i = 0; i < s; i++) {
if (!Objects.equals(es[i], otherEs[i])) {
equal = false;
break;
}
}
}
other.checkForComodification(otherModCount);
return equal;
}
private void checkForComodification(final int expectedModCount) {
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
/**
* {@inheritDoc}
*/
public int hashCode() {
int expectedModCount = modCount;
int hash = hashCodeRange(0, size);
checkForComodification(expectedModCount);
return hash;
}
int hashCodeRange(int from, int to) {
final Object[] es = elementData;
if (to > es.length) {
throw new ConcurrentModificationException();
}
int hashCode = 1;
for (int i = from; i < to; i++) {
Object e = es[i];
hashCode = 31 * hashCode + (e == null ? 0 : e.hashCode());
}
return hashCode;
}
/**
* Removes the first occurrence of the specified element from this list,
* if it is present. If the list does not contain the element, it is
* unchanged. More formally, removes the element with the lowest index
* {@code i} such that
* {@code Objects.equals(o, get(i))}
* (if such an element exists). Returns {@code true} if this list
* contained the specified element (or equivalently, if this list
* changed as a result of the call).
* 如果指定元素出现,移除这个 ArrayList 中第一次出现的元素。
* 如果 ArrayList 不包含这个元素,ArrayList 不会改变。
* @param o element to be removed from this list, if present 要删除的元素
* @return {@code true} if this list contained the specified element 如果包含指定的元素返回 true
*/
public boolean remove(Object o) {
final Object[] es = elementData;
final int size = this.size;
int i = 0;
found:
{
if (o == null) {
for (; i < size; i++)
if (es[i] == null)
break found;
} else {
for (; i < size; i++)
if (o.equals(es[i]))
break found;
}
return false;
}
fastRemove(es, i);
return true;
}
/**
* Private remove method that skips bounds checking and does not
* return the value removed.
* 跳过边界检查且不返回已删除值的私有移除方法。
*/
private void fastRemove(Object[] es, int i) {
modCount++;
final int newSize;
if ((newSize = size - 1) > i)// 要移动的长度
// 将 i+1 及其后面的元素复制到 i 及其后面的下标上
System.arraycopy(es, i + 1, es, i, newSize - i);
// 将最后一个位置置为空
es[size = newSize] = null;
}
/**
* Removes all of the elements from this list. The list will
* be empty after this call returns.
* 从此 ArrayList 删除所有元素,这个方法调用后,ArrayList 为空
*/
public void clear() {
modCount++;
final Object[] es = elementData;
for (int to = size, i = size = 0; i < to; i++)
es[i] = null;
}
/**
* Appends all of the elements in the specified collection to the end of
* this list, in the order that they are returned by the
* specified collection's Iterator. The behavior of this operation is
* undefined if the specified collection is modified while the operation
* is in progress. (This implies that the behavior of this call is
* undefined if the specified collection is this list, and this
* list is nonempty.)
* 将指定集合中的所有元素添加到这个 ArrayList 的末尾,并按指定集合的 Iterator 返回的顺序进行添加
* 该方法没有加锁,当一个线程正在将 c 中的元素加入 list 中,但同时有另一个线程在更改 c 中的元素,可能会有问题
* @param c collection containing elements to be added to this list
* 要追加的集合
* @return {@code true} if this list changed as a result of the call 如果 ArrayList 改变返回 true
* @throws NullPointerException if the specified collection is null
*/
public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray();
modCount++;
int numNew = a.length;// 要添加元素的个数
if (numNew == 0)
return false;
Object[] elementData;
final int s;
// 判断是否需要扩容
if (numNew > (elementData = this.elementData).length - (s = size))
// 扩容
elementData = grow(s + numNew);
System.arraycopy(a, 0, elementData, s, numNew);
size = s + numNew;
return true;
}
/**
* Inserts all of the elements in the specified collection into this
* list, starting at the specified position. Shifts the element
* currently at that position (if any) and any subsequent elements to
* the right (increases their indices). The new elements will appear
* in the list in the order that they are returned by the
* specified collection's iterator.
* 从指定位置开始,将指定集合中所有元素插入这个 ArrayList 中。
* 将当前位置的元素(如果有)和任何后续元素后移。
* 新元素将按指定集合的迭代器返回的顺序显示在列表中。
* 不会覆盖在 index 位置原有的值
* @param index index at which to insert the first element from the
* specified collection
* 插入指定集合的索引
* @param c collection containing elements to be added to this list
* 需要添加的集合
* @return {@code true} if this list changed as a result of the call 如果 ArrayList 改变返回 true
* @throws IndexOutOfBoundsException {@inheritDoc}
* @throws NullPointerException if the specified collection is null
*/
public boolean addAll(int index, Collection<? extends E> c) {
rangeCheckForAdd(index);
// 将 list 直接转为 Object[] 数组
Object[] a = c.toArray();
modCount++;
int numNew = a.length;// 要添加集合的元素数量
if (numNew == 0)
return false;
Object[] elementData;
final int s;
// 扩容判断
if (numNew > (elementData = this.elementData).length - (s = size))
elementData = grow(s + numNew);
int numMoved = s - index;// list 中要移动的数量
if (numMoved > 0)
System.arraycopy(elementData, index,
elementData, index + numNew,
numMoved);
System.arraycopy(a, 0, elementData, index, numNew);
size = s + numNew;
return true;
}
/**
* Removes from this list all of the elements whose index is between
* {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.
* Shifts any succeeding elements to the left (reduces their index).
* This call shortens the list by {@code (toIndex - fromIndex)} elements.
* (If {@code toIndex==fromIndex}, this operation has no effect.)
* 从 ArrayList 中移除索引在 fromIndex 和 toIndex 之间所有的元素
* 将所有元素向左移动(toIndex-fromIndex)个元素
* 如果 (toIndex==fromIndex)这个操作没有影响
* @throws IndexOutOfBoundsException if {@code fromIndex} or
* {@code toIndex} is out of range
* ({@code fromIndex < 0 ||
* toIndex > size() ||
* toIndex < fromIndex})
*/
protected void removeRange(int fromIndex, int toIndex) {
if (fromIndex > toIndex) {
throw new IndexOutOfBoundsException(
outOfBoundsMsg(fromIndex, toIndex));
}
modCount++;
shiftTailOverGap(elementData, fromIndex, toIndex);
}
/**
* Erases the gap from lo to hi, by sliding down following elements.
* 通过向下滑动以下元素来消除从lo到hi的间隙
*/
private void shiftTailOverGap(Object[] es, int lo, int hi) {
// size-hi 要移动的数量
System.arraycopy(es, hi, es, lo, size - hi);
// 将失效元素置空
for (int to = size, i = (size -= hi - lo); i < to; i++)
es[i] = null;
}
/**
* A version of rangeCheck used by add and addAll.
* 添加时检查索引是否越界
*/
private void rangeCheckForAdd(int index) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
/**
* Constructs an IndexOutOfBoundsException detail message.
* Of the many possible refactorings of the error handling code,
* this "outlining" performs best with both server and client VMs.
* 构建IndexOutOfBoundsException详细消息
*/
private String outOfBoundsMsg(int index) {
return "Index: " + index + ", Size: " + size;
}
/**
* A version used in checking (fromIndex > toIndex) condition
* 用于检查(fromIndex> toIndex)条件的版本
*/
private static String outOfBoundsMsg(int fromIndex, int toIndex) {
return "From Index: " + fromIndex + " > To Index: " + toIndex;
}
/**
* Removes from this list all of its elements that are contained in the
* specified collection.
* 从此 ArrayList 中删除指定的集合中包含的所有元素。
* @param c collection containing elements to be removed from this list
* 要从 list 中删除的元素的集合
* @return {@code true} if this list changed as a result of the call
* @throws ClassCastException if the class of an element of this list
* is incompatible with the specified collection
* (<a href="Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if this list contains a null element and the
* specified collection does not permit null elements
* (<a href="Collection.html#optional-restrictions">optional</a>),
* or if the specified collection is null
* @see Collection#contains(Object)
*/
public boolean removeAll(Collection<?> c) {
return batchRemove(c, false, 0, size);
}
/**
* Retains only the elements in this list that are contained in the
* specified collection. In other words, removes from this list all
* of its elements that are not contained in the specified collection.
* 仅保留 ArrayList 中指定集合中包含的元素。换句话说,从 ArrayList 中删除所有不包含在指定集合中的元素。
* @param c collection containing elements to be retained in this list
* @return {@code true} if this list changed as a result of the call
* @throws ClassCastException if the class of an element of this list
* is incompatible with the specified collection
* (<a href="Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if this list contains a null element and the
* specified collection does not permit null elements
* (<a href="Collection.html#optional-restrictions">optional</a>),
* or if the specified collection is null
* @see Collection#contains(Object)
*/
public boolean retainAll(Collection<?> c) {
return batchRemove(c, true, 0, size);
}
/**
* 批处理移除
* @param c 要移除的集合
* @param complement 是否是补集
* 如果true:移除list中除了c集合中的所有元素
* 如果false:移除list中 c集合中的元素
* @param from
* @param end
* @return
*/
boolean batchRemove(Collection<?> c, boolean complement,
final int from, final int end) {
// 检查要移除的集合不为空
Objects.requireNonNull(c);
final Object[] es = elementData;
int r;
// Optimize for initial run of survivors
for (r = from; ; r++) {
if (r == end)
return false;
if (c.contains(es[r]) != complement)
break;
}
int w = r++;
try {
for (Object e; r < end; r++)
if (c.contains(e = es[r]) == complement)
es[w++] = e;
} catch (Throwable ex) {
// Preserve behavioral compatibility with AbstractCollection,
// even if c.contains() throws.
System.arraycopy(es, r, es, w, end - r);
w += end - r;
throw ex;
} finally {
modCount += end - w;
shiftTailOverGap(es, w, end);
}
return true;
}
/**
* Saves the state of the {@code ArrayList} instance to a stream
* (that is, serializes it).
* 将 ArrayList 实例序列不啊
* @param s the stream
* @throws java.io.IOException if an I/O error occurs
* @serialData The length of the array backing the {@code ArrayList}
* instance is emitted (int), followed by all of its elements
* (each an {@code Object}) in the proper order.
*/
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
// Write out element count, and any hidden stuff
// 写出元素计数以及任何隐藏的内容
int expectedModCount = modCount;
s.defaultWriteObject();
// Write out size as capacity for behavioral compatibility with clone()
// 写出大小作为与clone()行为兼容的容量
s.writeInt(size);
// Write out all elements in the proper order.
// 按照正确的顺序写出所有元素。
for (int i = 0; i < size; i++) {
s.writeObject(elementData[i]);
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
/**
* Reconstitutes the {@code ArrayList} instance from a stream (that is,
* deserializes it).
* 从反序列化中重构 ArrayList 实例
* @param s the stream
* @throws ClassNotFoundException if the class of a serialized object
* could not be found
* @throws java.io.IOException if an I/O error occurs
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
// Read in size, and any hidden stuff
// 阅读大小以及任何隐藏的内容
s.defaultReadObject();
// Read in capacity
// 读入容量
s.readInt(); // ignored
if (size > 0) {
// like clone(), allocate array based upon size not capacity
// 像clone()一样,根据大小而不是容量分配数组
SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Object[].class, size);
Object[] elements = new Object[size];
// Read in all elements in the proper order.
// 按正确的顺序读入所有元素。
for (int i = 0; i < size; i++) {
elements[i] = s.readObject();
}
elementData = elements;
} else if (size == 0) {
elementData = EMPTY_ELEMENTDATA;
} else {
throw new java.io.InvalidObjectException("Invalid size: " + size);
}
}
/**
* Returns a list iterator over the elements in this list (in proper
* sequence), starting at the specified position in the list.
* The specified index indicates the first element that would be
* returned by an initial call to {@link ListIterator#next next}.
* An initial call to {@link ListIterator#previous previous} would
* return the element with the specified index minus one.
*
* <p>The returned list iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
*
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public ListIterator<E> listIterator(int index) {
rangeCheckForAdd(index);
return new ListItr(index);
}
/**
* Returns a list iterator over the elements in this list (in proper
* sequence).
*
* <p>The returned list iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
*
* @see #listIterator(int)
*/
public ListIterator<E> listIterator() {
return new ListItr(0);
}
/**
* Returns an iterator over the elements in this list in proper sequence.
*
* <p>The returned iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
*
* @return an iterator over the elements in this list in proper sequence
*/
public Iterator<E> iterator() {
return new Itr();
}
/**
* An optimized version of AbstractList.Itr
*/
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
// prevent creating a synthetic constructor
Itr() {
}
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
@Override
public void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
final int size = ArrayList.this.size;
int i = cursor;
if (i < size) {
final Object[] es = elementData;
if (i >= es.length)
throw new ConcurrentModificationException();
for (; i < size && modCount == expectedModCount; i++)
action.accept(elementAt(es, i));
// update once at end to reduce heap write traffic
cursor = i;
lastRet = i - 1;
checkForComodification();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
/**
* An optimized version of AbstractList.ListItr
*/
private class ListItr extends Itr implements ListIterator<E> {
ListItr(int index) {
super();
cursor = index;
}
public boolean hasPrevious() {
return cursor != 0;
}
public int nextIndex() {
return cursor;
}
public int previousIndex() {
return cursor - 1;
}
@SuppressWarnings("unchecked")
public E previous() {
checkForComodification();
int i = cursor - 1;
if (i < 0)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i;
return (E) elementData[lastRet = i];
}
public void set(E e) {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.set(lastRet, e);
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
public void add(E e) {
checkForComodification();
try {
int i = cursor;
ArrayList.this.add(i, e);
cursor = i + 1;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
}
/**
* Returns a view of the portion of this list between the specified
* {@code fromIndex}, inclusive, and {@code toIndex}, exclusive. (If
* {@code fromIndex} and {@code toIndex} are equal, the returned list is
* empty.) The returned list is backed by this list, so non-structural
* changes in the returned list are reflected in this list, and vice-versa.
* The returned list supports all of the optional list operations.
*
* <p>This method eliminates the need for explicit range operations (of
* the sort that commonly exist for arrays). Any operation that expects
* a list can be used as a range operation by passing a subList view
* instead of a whole list. For example, the following idiom
* removes a range of elements from a list:
* <pre>
* list.subList(from, to).clear();
* </pre>
* Similar idioms may be constructed for {@link #indexOf(Object)} and
* {@link #lastIndexOf(Object)}, and all of the algorithms in the
* {@link Collections} class can be applied to a subList.
*
* <p>The semantics of the list returned by this method become undefined if
* the backing list (i.e., this list) is <i>structurally modified</i> in
* any way other than via the returned list. (Structural modifications are
* those that change the size of this list, or otherwise perturb it in such
* a fashion that iterations in progress may yield incorrect results.)
*
* @throws IndexOutOfBoundsException {@inheritDoc}
* @throws IllegalArgumentException {@inheritDoc}
*/
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size);
return new SubList<>(this, fromIndex, toIndex);
}
private static class SubList<E> extends AbstractList<E> implements RandomAccess {
private final ArrayList<E> root;
private final SubList<E> parent;
private final int offset;
private int size;
/**
* Constructs a sublist of an arbitrary ArrayList.
*/
public SubList(ArrayList<E> root, int fromIndex, int toIndex) {
this.root = root;
this.parent = null;
this.offset = fromIndex;
this.size = toIndex - fromIndex;
this.modCount = root.modCount;
}
/**
* Constructs a sublist of another SubList.
*/
private SubList(SubList<E> parent, int fromIndex, int toIndex) {
this.root = parent.root;
this.parent = parent;
this.offset = parent.offset + fromIndex;
this.size = toIndex - fromIndex;
this.modCount = root.modCount;
}
public E set(int index, E element) {
Objects.checkIndex(index, size);
checkForComodification();
E oldValue = root.elementData(offset + index);
root.elementData[offset + index] = element;
return oldValue;
}
public E get(int index) {
Objects.checkIndex(index, size);
checkForComodification();
return root.elementData(offset + index);
}
public int size() {
checkForComodification();
return size;
}
public void add(int index, E element) {
rangeCheckForAdd(index);
checkForComodification();
root.add(offset + index, element);
updateSizeAndModCount(1);
}
public E remove(int index) {
Objects.checkIndex(index, size);
checkForComodification();
E result = root.remove(offset + index);
updateSizeAndModCount(-1);
return result;
}
protected void removeRange(int fromIndex, int toIndex) {
checkForComodification();
root.removeRange(offset + fromIndex, offset + toIndex);
updateSizeAndModCount(fromIndex - toIndex);
}
public boolean addAll(Collection<? extends E> c) {
return addAll(this.size, c);
}
public boolean addAll(int index, Collection<? extends E> c) {
rangeCheckForAdd(index);
int cSize = c.size();
if (cSize == 0)
return false;
checkForComodification();
root.addAll(offset + index, c);
updateSizeAndModCount(cSize);
return true;
}
public void replaceAll(UnaryOperator<E> operator) {
root.replaceAllRange(operator, offset, offset + size);
}
public boolean removeAll(Collection<?> c) {
return batchRemove(c, false);
}
public boolean retainAll(Collection<?> c) {
return batchRemove(c, true);
}
private boolean batchRemove(Collection<?> c, boolean complement) {
checkForComodification();
int oldSize = root.size;
boolean modified =
root.batchRemove(c, complement, offset, offset + size);
if (modified)
updateSizeAndModCount(root.size - oldSize);
return modified;
}
public boolean removeIf(Predicate<? super E> filter) {
checkForComodification();
int oldSize = root.size;
boolean modified = root.removeIf(filter, offset, offset + size);
if (modified)
updateSizeAndModCount(root.size - oldSize);
return modified;
}
public Object[] toArray() {
checkForComodification();
return Arrays.copyOfRange(root.elementData, offset, offset + size);
}
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
checkForComodification();
if (a.length < size)
return (T[]) Arrays.copyOfRange(
root.elementData, offset, offset + size, a.getClass());
System.arraycopy(root.elementData, offset, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof List)) {
return false;
}
boolean equal = root.equalsRange((List<?>) o, offset, offset + size);
checkForComodification();
return equal;
}
public int hashCode() {
int hash = root.hashCodeRange(offset, offset + size);
checkForComodification();
return hash;
}
public int indexOf(Object o) {
int index = root.indexOfRange(o, offset, offset + size);
checkForComodification();
return index >= 0 ? index - offset : -1;
}
public int lastIndexOf(Object o) {
int index = root.lastIndexOfRange(o, offset, offset + size);
checkForComodification();
return index >= 0 ? index - offset : -1;
}
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
public Iterator<E> iterator() {
return listIterator();
}
public ListIterator<E> listIterator(int index) {
checkForComodification();
rangeCheckForAdd(index);
return new ListIterator<E>() {
int cursor = index;
int lastRet = -1;
int expectedModCount = root.modCount;
public boolean hasNext() {
return cursor != SubList.this.size;
}
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= SubList.this.size)
throw new NoSuchElementException();
Object[] elementData = root.elementData;
if (offset + i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[offset + (lastRet = i)];
}
public boolean hasPrevious() {
return cursor != 0;
}
@SuppressWarnings("unchecked")
public E previous() {
checkForComodification();
int i = cursor - 1;
if (i < 0)
throw new NoSuchElementException();
Object[] elementData = root.elementData;
if (offset + i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i;
return (E) elementData[offset + (lastRet = i)];
}
public void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
final int size = SubList.this.size;
int i = cursor;
if (i < size) {
final Object[] es = root.elementData;
if (offset + i >= es.length)
throw new ConcurrentModificationException();
for (; i < size && modCount == expectedModCount; i++)
action.accept(elementAt(es, offset + i));
// update once at end to reduce heap write traffic
cursor = i;
lastRet = i - 1;
checkForComodification();
}
}
public int nextIndex() {
return cursor;
}
public int previousIndex() {
return cursor - 1;
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
SubList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = root.modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
public void set(E e) {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
root.set(offset + lastRet, e);
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
public void add(E e) {
checkForComodification();
try {
int i = cursor;
SubList.this.add(i, e);
cursor = i + 1;
lastRet = -1;
expectedModCount = root.modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
final void checkForComodification() {
if (root.modCount != expectedModCount)
throw new ConcurrentModificationException();
}
};
}
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size);
return new SubList<>(this, fromIndex, toIndex);
}
private void rangeCheckForAdd(int index) {
if (index < 0 || index > this.size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
private String outOfBoundsMsg(int index) {
return "Index: " + index + ", Size: " + this.size;
}
private void checkForComodification() {
if (root.modCount != modCount)
throw new ConcurrentModificationException();
}
private void updateSizeAndModCount(int sizeChange) {
SubList<E> slist = this;
do {
slist.size += sizeChange;
slist.modCount = root.modCount;
slist = slist.parent;
} while (slist != null);
}
public Spliterator<E> spliterator() {
checkForComodification();
// ArrayListSpliterator not used here due to late-binding
return new Spliterator<E>() {
private int index = offset; // current index, modified on advance/split
private int fence = -1; // -1 until used; then one past last index
private int expectedModCount; // initialized when fence set
private int getFence() { // initialize fence to size on first use
int hi; // (a specialized variant appears in method forEach)
if ((hi = fence) < 0) {
expectedModCount = modCount;
hi = fence = offset + size;
}
return hi;
}
public ArrayList<E>.ArrayListSpliterator trySplit() {
int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
// ArrayListSpliterator can be used here as the source is already bound
return (lo >= mid) ? null : // divide range in half unless too small
root.new ArrayListSpliterator(lo, index = mid, expectedModCount);
}
public boolean tryAdvance(Consumer<? super E> action) {
Objects.requireNonNull(action);
int hi = getFence(), i = index;
if (i < hi) {
index = i + 1;
@SuppressWarnings("unchecked") E e = (E) root.elementData[i];
action.accept(e);
if (root.modCount != expectedModCount)
throw new ConcurrentModificationException();
return true;
}
return false;
}
public void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
int i, hi, mc; // hoist accesses and checks from loop
ArrayList<E> lst = root;
Object[] a;
if ((a = lst.elementData) != null) {
if ((hi = fence) < 0) {
mc = modCount;
hi = offset + size;
} else
mc = expectedModCount;
if ((i = index) >= 0 && (index = hi) <= a.length) {
for (; i < hi; ++i) {
@SuppressWarnings("unchecked") E e = (E) a[i];
action.accept(e);
}
if (lst.modCount == mc)
return;
}
}
throw new ConcurrentModificationException();
}
public long estimateSize() {
return getFence() - index;
}
public int characteristics() {
return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
}
};
}
}
/**
* @throws NullPointerException {@inheritDoc}
*/
@Override
public void forEach(Consumer<? super E> action) {
Objects.requireNonNull(action);
final int expectedModCount = modCount;
final Object[] es = elementData;
final int size = this.size;
for (int i = 0; modCount == expectedModCount && i < size; i++)
action.accept(elementAt(es, i));
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
/**
* Creates a <em><a href="Spliterator.html#binding">late-binding</a></em>
* and <em>fail-fast</em> {@link Spliterator} over the elements in this
* list.
*
* <p>The {@code Spliterator} reports {@link Spliterator#SIZED},
* {@link Spliterator#SUBSIZED}, and {@link Spliterator#ORDERED}.
* Overriding implementations should document the reporting of additional
* characteristic values.
*
* @return a {@code Spliterator} over the elements in this list
* @since 1.8
*/
@Override
public Spliterator<E> spliterator() {
return new ArrayListSpliterator(0, -1, 0);
}
/**
* Index-based split-by-two, lazily initialized Spliterator
*/
final class ArrayListSpliterator implements Spliterator<E> {
/*
* If ArrayLists were immutable, or structurally immutable (no
* adds, removes, etc), we could implement their spliterators
* with Arrays.spliterator. Instead we detect as much
* interference during traversal as practical without
* sacrificing much performance. We rely primarily on
* modCounts. These are not guaranteed to detect concurrency
* violations, and are sometimes overly conservative about
* within-thread interference, but detect enough problems to
* be worthwhile in practice. To carry this out, we (1) lazily
* initialize fence and expectedModCount until the latest
* point that we need to commit to the state we are checking
* against; thus improving precision. (This doesn't apply to
* SubLists, that create spliterators with current non-lazy
* values). (2) We perform only a single
* ConcurrentModificationException check at the end of forEach
* (the most performance-sensitive method). When using forEach
* (as opposed to iterators), we can normally only detect
* interference after actions, not before. Further
* CME-triggering checks apply to all other possible
* violations of assumptions for example null or too-small
* elementData array given its size(), that could only have
* occurred due to interference. This allows the inner loop
* of forEach to run without any further checks, and
* simplifies lambda-resolution. While this does entail a
* number of checks, note that in the common case of
* list.stream().forEach(a), no checks or other computation
* occur anywhere other than inside forEach itself. The other
* less-often-used methods cannot take advantage of most of
* these streamlinings.
*/
private int index; // current index, modified on advance/split
private int fence; // -1 until used; then one past last index
private int expectedModCount; // initialized when fence set
/**
* Creates new spliterator covering the given range.
*/
ArrayListSpliterator(int origin, int fence, int expectedModCount) {
this.index = origin;
this.fence = fence;
this.expectedModCount = expectedModCount;
}
private int getFence() { // initialize fence to size on first use
int hi; // (a specialized variant appears in method forEach)
if ((hi = fence) < 0) {
expectedModCount = modCount;
hi = fence = size;
}
return hi;
}
public ArrayListSpliterator trySplit() {
int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
return (lo >= mid) ? null : // divide range in half unless too small
new ArrayListSpliterator(lo, index = mid, expectedModCount);
}
public boolean tryAdvance(Consumer<? super E> action) {
if (action == null)
throw new NullPointerException();
int hi = getFence(), i = index;
if (i < hi) {
index = i + 1;
@SuppressWarnings("unchecked") E e = (E) elementData[i];
action.accept(e);
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
return true;
}
return false;
}
public void forEachRemaining(Consumer<? super E> action) {
int i, hi, mc; // hoist accesses and checks from loop
Object[] a;
if (action == null)
throw new NullPointerException();
if ((a = elementData) != null) {
if ((hi = fence) < 0) {
mc = modCount;
hi = size;
} else
mc = expectedModCount;
if ((i = index) >= 0 && (index = hi) <= a.length) {
for (; i < hi; ++i) {
@SuppressWarnings("unchecked") E e = (E) a[i];
action.accept(e);
}
if (modCount == mc)
return;
}
}
throw new ConcurrentModificationException();
}
public long estimateSize() {
return getFence() - index;
}
public int characteristics() {
return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
}
}
// A tiny bit set implementation
private static long[] nBits(int n) {
return new long[((n - 1) >> 6) + 1];
}
private static void setBit(long[] bits, int i) {
bits[i >> 6] |= 1L << i;
}
private static boolean isClear(long[] bits, int i) {
return (bits[i >> 6] & (1L << i)) == 0;
}
/**
* @throws NullPointerException {@inheritDoc}
*/
@Override
public boolean removeIf(Predicate<? super E> filter) {
return removeIf(filter, 0, size);
}
/**
* Removes all elements satisfying the given predicate, from index
* i (inclusive) to index end (exclusive).
*/
boolean removeIf(Predicate<? super E> filter, int i, final int end) {
Objects.requireNonNull(filter);
int expectedModCount = modCount;
final Object[] es = elementData;
// Optimize for initial run of survivors
for (; i < end && !filter.test(elementAt(es, i)); i++)
;
// Tolerate predicates that reentrantly access the collection for
// read (but writers still get CME), so traverse once to find
// elements to delete, a second pass to physically expunge.
if (i < end) {
final int beg = i;
final long[] deathRow = nBits(end - beg);
deathRow[0] = 1L; // set bit 0
for (i = beg + 1; i < end; i++)
if (filter.test(elementAt(es, i)))
setBit(deathRow, i - beg);
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
modCount++;
int w = beg;
for (i = beg; i < end; i++)
if (isClear(deathRow, i - beg))
es[w++] = es[i];
shiftTailOverGap(es, w, end);
return true;
} else {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
return false;
}
}
@Override
public void replaceAll(UnaryOperator<E> operator) {
replaceAllRange(operator, 0, size);
modCount++;
}
private void replaceAllRange(UnaryOperator<E> operator, int i, int end) {
Objects.requireNonNull(operator);
final int expectedModCount = modCount;
final Object[] es = elementData;
for (; modCount == expectedModCount && i < end; i++)
es[i] = operator.apply(elementAt(es, i));
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
@Override
@SuppressWarnings("unchecked")
public void sort(Comparator<? super E> c) {
final int expectedModCount = modCount;
Arrays.sort((E[]) elementData, 0, size, c);
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
modCount++;
}
void checkInvariants() {
// assert size >= 0;
// assert size == elementData.length || elementData[size] == null;
}
}
2.6 如何在阅读 ArrayList 源码时添加注释
- 创建一个 ArrayList 类;
- 将代码拷贝进来,同时创建一个 AbstractList 抽象类,也将代码拷贝进去;
- 剩下的就是导一些包就行了。
三、ArrayList 相关知识
3.1 ArrayList 的 fail-fast
modCount 用来记录 ArrayList 结构发生变化的次数。
结构发生变化是指添加或删除至少一个元素的所有操作,仅设置元素的值不算结构发生变化。
在进行序列化或者迭代等操作时,需要比较操作前后 modCount 是否改变,如果改变了需要抛出
3.2 list 的遍历方式选择
- 实现了 RandomAccess 接口的 list,优先选择普通 for 循环,其次 foreach
- 未实现了 RandomAccess 接口的 list,优先选择 iterator 遍历,大 size 的数据,千万不要使用普通 for 循环
3.3 ArrayList 和 Vector 比较
- Vector 是同步的,因此开销比 ArrayList 大,访问速度更慢。最好使用 ArrayList 而不是 Vector,因为同步操作完全可以由程序员自己来控制;
- Vector 每次扩容请求其大小的 2 倍空间,而 ArrayList 是 1.5 倍。
3.4 为啥线程不安全还是用 ArrayList
因为在正常使用的场景中,都是用来查询,不会涉及太频繁的增删。