源码分析
属性分析
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.
存储ArrayList元素的数组缓冲区。 * ArrayList的容量是此数组缓冲区的长度。添加第一个元素时,任何具有 elementData == 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).
* ArrayList的大小(它包含的元素数)。
* @serial
*/
private int size; // 默认值为0
/**
* The number of times this list has been <i>structurally modified</i>.
* Structural modifications are those that change the size of the
* list, or otherwise perturb it in such a fashion that iterations in
* progress may yield incorrect results.
*
* <p>This field is used by the iterator and list iterator implementation
* returned by the {@code iterator} and {@code listIterator} methods.
* If the value of this field changes unexpectedly, the iterator (or list
* iterator) will throw a {@code ConcurrentModificationException} in
* response to the {@code next}, {@code remove}, {@code previous},
* {@code set} or {@code add} operations. This provides
* <i>fail-fast</i> behavior, rather than non-deterministic behavior in
* the face of concurrent modification during iteration.
*
* <p><b>Use of this field by subclasses is optional.</b> If a subclass
* wishes to provide fail-fast iterators (and list iterators), then it
* merely has to increment this field in its {@code add(int, E)} and
* {@code remove(int)} methods (and any other methods that it overrides
* that result in structural modifications to the list). A single call to
* {@code add(int, E)} or {@code remove(int)} must add no more than
* one to this field, or the iterators (and list iterators) will throw
* bogus {@code ConcurrentModificationExceptions}. If an implementation
* does not wish to provide fail-fast iterators, this field may be
* ignored.
此列表被<i>结构修改</ i>的次数。 *结构性修改是指更改*列表大小,或以其他方式干扰列表*进行迭代可能会产生错误结果的方式。 * * <p> {@ code iterator}和{@code listIterator}方法返回的迭代器和列表迭代器实现使用此字段。 *如果此字段的值意外更改,则迭代器(或列表*迭代器)将在对{@code next},{@ code remove},{@ code previous},*的响应中抛出{@code ConcurrentModificationException} {@code set}或{@code add}操作。这提供了* i-fail-fast </ i>行为,而不是*在迭代过程中面对并发修改时具有不确定性。 * * <p> <b>子类对该字段的使用是可选的。</ b>如果子类*希望提供快速失败的迭代器(和列表迭代器),则它仅需要在其{ @code add(int,E)}和* {@code remove(int)}方法(以及它覆盖的所有其他方法*会导致对该列表进行结构修改)。一次调用* {@code add(int,E)}或{@code remove(int)}不得在此字段中添加*个以上的字符,否则迭代器(和列表迭代器)将抛出假冒的{@code ConcurrentModificationExceptions}。如果实现不希望提供快速失败的迭代器,则可以忽略此字段。
*/
protected transient int modCount = 0; //保证迭代当中集合不被修改,修改则会抛出ConcurrentModificationException,提供快速失败的迭代器,则可以忽略此字段。
/**
* 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
要分配的最大数组大小。 *一些虚拟机在数组中保留一些标题字。 *尝试分配更大的阵列可能会导致* OutOfMemoryError:请求的阵列大小超出VM限制
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
方法分析
add
/**
* 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})
*/
public boolean add(E e) {
// 确保内部容量可以存下当前数据,如果初始化时无参构造器,则第一次调用add方法再对底层数组初始化。
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
// 第一次初始化获取 DEFAULT_CAPACITY 和 传入值 最大值初始化底层数组
private void ensureCapacityInternal(int minCapacity) {
// 第一次进入 minCapacity =(size + 1),size为成员变量默认为0,所以第一次为1
// 调用的无参构造器 elementData 默认就是 EMPTY_ELEMENTDATA
if (elementData == EMPTY_ELEMENTDATA) {
// DEFAULT_CAPACITY 默认值为10 minCapacity = 1
// 第一次初始化会进入这个方法,取最大值初始化
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
// minCapacity 存取的第几个数据 (第一次例外)
ensureExplicitCapacity(minCapacity);
}
// 决定是否需要扩容
private void ensureExplicitCapacity(int minCapacity) {
// minCapacity = 10
// modCount 记录集合被修改的次数,快速响应一个迭代出错。 意思为迭代的时候,有其他地方动了集合的数
// 据。快速的响应抛出异常
modCount++;
// overflow-conscious code 有溢出意识的代码
//(第一次为 10,后面为需要存入数据的索引(size + 1)数组长度从1开始,所以集合索引需要加一判断,正好够存入这个数据,则不扩容)
// 如果当前需要存入的第几个数据 大于 集合的长度
if (minCapacity - elementData.length > 0)
// 增长,扩容内部数组
grow(minCapacity);
}
/**
* 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
增加容量,以确保它至少可以容纳最小容量参数指定的*个元素。 * * @param minCapacity所需的最小容量
*/
private void grow(int minCapacity) {
// overflow-conscious code
// 得到老数组的长度
int oldCapacity = elementData.length;
// 计算新 数组的长度 = 老数组 * 1.5 内存溢出后为负数
int newCapacity = oldCapacity + (oldCapacity >> 1);
// 如果新数组 小于 当前需要存入的第几个数据 (一些特殊的数值才会进入,0*1.5 = 0 1*1.5 = 1.5 )
if (newCapacity - minCapacity < 0)
// 只有当存不下这个长度的数据才会进来 内存溢出也会进入
newCapacity = minCapacity;
// 如果新数组的长度已经 大于 Integer.MAX_VALUE - 8 数组已经很庞大了
if (newCapacity - MAX_ARRAY_SIZE > 0)
// 决定新数组的大小
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
// 底层数组的 复制返回新数组 复制长度为 Math.min(elementData.length, newCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
// 决定数组大小
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow 已经内存溢出了过了
throw new OutOfMemoryError();
// 当前需要存入的第几个数据 大于 Integer.MAX_VALUE - 8 成立 ? Integer.MAX_VALUE 不成立 Integer.MAX_VALUE - 8
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
get
/**
* 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}
返回此列表中指定位置的元素。 * * @要返回的元素的索引索引* @返回此列表中指定位置的元素* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
/**
* Checks if the given index is in range. If not, throws an appropriate
* runtime exception. This method does *not* check if the index is
* negative: It is always used immediately prior to an array access,
* which throws an ArrayIndexOutOfBoundsException if index is negative.
如果给定的索引在范围内,则返回。如果不是,则抛出适当的*运行时异常。此方法不检查索引是否为负数:始终在访问数组之前立即使用它,如果索引为负数,则抛出ArrayIndexOutOfBoundsException。
*/
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
remove
/**
* 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}
/ ** *删除此列表中指定位置的元素。 *将所有后续元素向左移动(从它们的*索引中减去一个)。 * * @param index要删除的元素的索引* @返回从列表中删除的元素* @throws IndexOutOfBoundsException {@inheritDoc} * /
*/
// 根据下标删除元素
public E remove(int index) {
// 检查下标是否越界 不检查索引是否为负数
rangeCheck(index);
// 操作次数加1
modCount++;
// 拿到需要删除的值返回
E oldValue = elementData(index);
// 需要复制的数组长度
int numMoved = size - index - 1;
// 如果=0 说明是最后一个元素直接删除即可,不是最后一个需要进行一个复制操作
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
// 最后一个赋值为null,删除后数据全部往左推
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
** *从此列表中删除第一次出现的指定元素,如果存在*。如果列表不包含元素,则*不变。更正式地,删除具有最低索引* <tt> i </ tt>的元素,使得* <tt>(o == null?get(i)== null:o.equals(get(i)))< / tt> *(如果存在这样的元素)。如果此列表*包含指定的元素,则返回<tt> true </ tt>(或者等效地,如果此列表*由于调用而更改),则返回<tt> true </ tt>。 * * @param o要从此列表中删除的元素(如果存在)* @return <tt> true </ tt>如果此列表包含指定的元素* /
*/
// 根据对象删除元素,返回此集合是否包含此传入的元素
public boolean remove(Object o) {
// 判断对象为不为null
if (o == null) {
// 循环遍历删除
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
// 传入索引删除
fastRemove(index);
return true;
}
} else {
// 循环遍历删除
for (int index = 0; index < size; index++)
// 底层条用equals进行比较,如果是对象可以重写equals方法来达到需要的效果
if (o.equals(elementData[index])) {
// 传入索引删除
fastRemove(index);
return true;
}
}
return false;
}
// 没有重写的equals方法
public boolean equals(Object obj) {
return (this == obj);
}
// 快速删除方法
/*
* Private remove method that skips bounds checking and does not
* return the value removed.
专用的remove方法,跳过边界检查,并且不返回删除的值
*/
private void fastRemove(int index) {
// 操作数加1
modCount++;
// 得到需要复制的数组长度
int numMoved = size - index - 1;
// 如果不是最后一个元素
if (numMoved > 0)
// 开始复制 原数组 从原数组哪个下标开始复制
System.arraycopy(elementData, index+1, elementData // 目标数组
, index, // 从数组哪个下标开始复制
numMoved // 复制的长度
);
// 最后一个元置空
elementData[--size] = null; // clear to let GC do its work
}
contains
/**
* 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
/ ** *如果此列表包含指定的元素,则返回<tt> true </ tt>。 *更正式地讲,当且仅当此列表包含*至少一个元素<tt> e </ tt>使得* <tt>(o == null?e == null: o.equals(e))</ tt>。 * * @param o要在此列表中进行测试的元素* @return <tt> true </ tt>如果此列表包含指定的元素* /
*/
// 判断此集合是否包含元素
public boolean contains(Object o) {
// 如果返回的下标大于等于0 说明此列表中包含此元素
return indexOf(o) >= 0;
}
indexOf
/**
* 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.
返回指定元素在此列表中首次出现的索引*,如果此列表不包含该元素,则返回-1。 *更正式地,返回最低索引<tt> i </ tt>以便* <tt>(o == null?get(i)== null:o.equals(get(i)))</ tt> ,*或-1(如果没有这样的索引)。
*/
public int indexOf(Object o) {
// 判断是否为null
if (o == null) {
// 循环遍历 返回首次出现的下标
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
// 循环遍历 返回首次出现的下标,调用equals进行比较
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
// 返回首次出现的下标
return i;
}
// 没有找到返回 -1
return -1;
}
size
/**
* Returns the number of elements in this list.
*
* @return the number of elements in this list
*/
public int size() {
// 直接返回内部属性值
return size;
}
clear
/**
* Removes all of the elements from this list. The list will
* be empty after this call returns.
/ ** *从此列表中删除所有元素。该调用返回后,列表将*为空。 * /
*/
public void clear() {
// 操作次数加1
modCount++;
// clear to let GC do its work
// 循环将数组置为空
for (int i = 0; i < size; i++)
elementData[i] = null;
// 成员变量 size 变为 0
size = 0;
}
toArray
/**
* 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
/ ** *以正确的顺序(从第一个到最后一个元素)返回一个包含此列表中所有元素的数组。 * * <p>返回的数组将是“安全的”,因为此列表不保留对其的引用。 (换句话说,此方法必须分配*一个新数组)。因此,调用者可以自由修改返回的数组。 * * <p>此方法充当基于数组的API和基于集合的API之间的桥梁。 * * @以正确的顺序返回包含此列表中所有元素的数组* /
*/
public Object[] toArray() {
// 需要复制的数组, 需要复制的长度
return Arrays.copyOf(elementData, size);
}
addAll
/**
* 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
/ ** *按指定集合的Iterator返回的顺序,将指定集合中的所有元素追加到此列表的末尾。如果在操作过程中修改了指定的集合,则该操作的行为是不确定的。 (这意味着如果指定的集合是此列表,并且此列表是非空的,则此调用的行为是* undefined。)* * @param c集合,其中包含要添加到此列表的元素* @return <tt> true < / tt>如果此列表由于调用而更改* @throws NullPointerException如果指定的集合为null * /
*/
public boolean addAll(Collection<? extends E> c) {
// 将集合转为一个复制后的数组
Object[] a = c.toArray();
// 获取数组长度
int numNew = a.length;
// 判断现在的集合是否存的下size + numNew 长的数据
ensureCapacityInternal(size + numNew); // Increments modCount
// 复制
System.arraycopy(a, 0, elementData, size, numNew);
// 更改下标
size += numNew;
// 返回此次是否做了更改
return numNew != 0;
}
iterator
/**
* 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
以正确的顺序返回此列表中元素的迭代器。
<p>返回的迭代器为<a href="#fail-fast">
<i>失败快速</ i> </a>。
以正确的顺序返回此列表中元素的迭代器
*/
public Iterator<E> iterator() {
// new 了一个实现了 Iterator接口的内部类
return new Itr();
}
/**
* An optimized version of AbstractList.Itr
*/
private class Itr implements Iterator<E> {
int cursor; //下一个要返回的元素的索引
int lastRet = -1; //返回的最后一次取出的元素索引; -1(如果没有)
// 保存 modCount 修改的次数
int expectedModCount = modCount;
// 是否还有下一个
public boolean hasNext() {
// cursor默认值为0
return cursor != size;
}
// 下一个数据
@SuppressWarnings("unchecked")
public E next() {
// 检查是数组是否被修改
checkForComodification();
// 取得元素的下标索引,从0开始
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() {
// 判断有没有取出过元素,lastRet代表最后一次取出的元素索引,没取出过默认值为-1
if (lastRet < 0)
throw new IllegalStateException();
// 检查运行期间数组状态是否发生了变动
checkForComodification();
try {
// 尝试调用普通的下标删除方法去删除,最后一次取出的元素索引。
ArrayList.this.remove(lastRet);
// 下标回滚一次,因为底层数组已经重排序
cursor = lastRet;
// 最后一次取出的元素也往前推一个,当前元素删除,经过重排序,现在的lastRet为删除前的元素值,没有取出过,需要往前推一个
lastRet = -1;
// 更新操作次数,因为此次状态的变化是自己调用 remove产生的记过。
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
// 下标越界,数组删除期间,底层数组状态发生了变化。
throw new ConcurrentModificationException();
}
}
@Override
@SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> consumer) {
Objects.requireNonNull(consumer);
final int size = ArrayList.this.size;
int i = cursor;
if (i >= size) {
return;
}
final Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length) {
throw new ConcurrentModificationException();
}
while (i != size && modCount == expectedModCount) {
consumer.accept((E) elementData[i++]);
}
// update once at end of iteration to reduce heap write traffic
cursor = i;
lastRet = i - 1;
checkForComodification();
}
// 检查迭代期间内部数组有没有发生过状态的变化,发生了变化就快速失败抛出
// ConcurrentModificationException
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}