本文主要针对 JDK1.8 的 ArrayList
源码进行解析,主要看源码注释,代码说明了全部实现细节。
ArrayList
的继承结构如下图所示,下面我们进行一一解析。
Serializable
接口是启用其序列化功能的接口,接口定义如下:
public interface Serializable {
}
实现 java.io.Serializable
接口的类是可序列化的,在序列化和反序列化过程中需要特殊处理的类必须使用下列准确签名来实现特殊方法:
private void writeObject(java.io.ObjectOutputStream out) throws IOException;
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;
ArrayList
由于内部数组具有冗余,所以通过这两种方法来进行去冗余序列化。
RandomAccess
接口是标记接口,内容为空。该标记接口表示该集合支持随机访问,接口定义如下:
public interface RandomAccess {
}
ArrayList
实现 RandomAccess
接口,LinkedList
并没有实现 RandomAccess
接口,随机访问影响我们在遍历列表的时候是用下标的方式还是迭代器的方式,从性能上看 对于支持快速随机访问的集合,下标的方式更快,迭代器较慢;不支持快速随机访问的集合,迭代器更快,下标的方式很慢。
那么如何判断一个集合是否支持随机访问呢?
通过 instanceof
判断集合是否实现了 RandomAccess
接口。
具体可参考:https://blog.csdn.net/weixin_39148512/article/details/79234817
Cloneable
接口也是一个标记接口,当然也就是空接口。
public interface Cloneable {
}
类只有实现这个接口,然后在类中重写 Object
中的 clone()
方法,这样对象实例调用 clone()
方法才能克隆成功,缺一不可。如果不实现这个接口,直接调用 clone()
方法则会抛出 CloneNotSupportedException
异常。
查看 Object
中定义的 clone()
方法:
protected native Object clone() throws CloneNotSupportedException;
该方法为 native 方法,本地方法会在其中判断是否实现 Cloneable
接口,同时==该方法默认是浅拷贝==。
关于浅拷贝、深拷贝的概念,可以参考:https://blog.csdn.net/xinghuo0007/article/details/78896726
一个集类要表明自己支持迭代,能有使用 foreach
语句的特权,就必须实现 Iterable
接口,表明是可迭代的。实现Iterable接口,需为 foreach
语句提供一个迭代器 Iterator
,迭代器通过 iterator()
方法返回。
public interface Iterable<T> {
// 返回迭代器
Iterator<T> iterator();
// =======以下是JDK1.8之后加入的,为lambda表达式准备的方法=======
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}
迭代器 Iterator
也是一个接口,接口包含3个基本方法,jdk1.8之后又加入一个。
public interface Iterator<E> {
boolean hasNext();
E next();
// 删除最近一次已经迭代出的元素
default void remove() {
throw new UnsupportedOperationException("remove");
}
// =======JDK1.8之后加入的,为lambda表达式准备的方法=======
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
Collection
定义了一些集合的公共行为,源码如下:
public interface Collection<E> extends Iterable<E> {
// Query Operations
boolean isEmpty();
boolean contains(Object o);
Iterator<E> iterator();
/**
* 按序返回一个数组,数组包含集合中的元素。返回的泛型也丢失了
* 返回的数组是安全的,即集合不存在指向数组的任何引用
* 该方法充当集合到数组的转化桥梁
*/
Object[] toArray();
/**
* 返回包含此collection中所有元素的数组
* 返回数组的运行时类型是指定数组的运行时类型
* 如果集合适合指定的数组,则返回其中
* 否则,将使用指定数组的运行时类型和此集合的大小分配一个新数组
*/
<T> T[] toArray(T[] a);
// Modification Operations
/**
* 向集合中尝试添加元素,可能不让添加,具体看集合对元素要求
*/
boolean add(E e);
/**
* 尝试删除一个元素
*/
boolean remove(Object o);
// Bulk Operations 块操作
/**
* 集合是否包含c中的所有元素
*/
boolean containsAll(Collection<?> c);
/**
* 尝试添加c的所有元素
*/
boolean addAll(Collection<? extends E> c);
/**
* 尝试删除c中含有的所有元素
*/
boolean removeAll(Collection<?> c);
// jdk1.8新方法
default boolean removeIf(Predicate<? super E> filter) {
Objects.requireNonNull(filter);
boolean removed = false;
final Iterator<E> each = iterator();
while (each.hasNext()) {
if (filter.test(each.next())) {
each.remove();
removed = true;
}
}
return removed;
}
/**
* 相当于求与c的交集
*/
boolean retainAll(Collection<?> c);
/**
* 清空集合
*/
void clear();
// Comparison and hashing
boolean equals(Object o);
int hashCode();
// jdk1.8新方法
@Override
default Spliterator<E> spliterator() {
return Spliterators.spliterator(this, 0);
}
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
default Stream<E> parallelStream() {
return StreamSupport.stream(spliterator(), true);
}
}
为何是实现 Iterable
这个接口而不直接实现 Iterator
接口?
实现 Iterable
这个接口 Collection
集合调用一次 iterator()
即可返回一个新的迭代器实例,迭代器的实现是依赖于游标的,如果 Collection
集合直接实现 Iterator
接口,相当于一个集合实例对应只有一个迭代器,那么集合的多个遍历者共用一个迭代器的游标会出问题。现在多个遍历者可以每个人自己调用 iterator()
返回专属的迭代器(专属的游标),不会冲突。
List
接口继承自 Collection
接口,额外定义了一些列表特有的行为,主要为了区分于 Set
等。
/**
* 有序、允许重复的集合,用户可以通过下表进行访问元素
*
* 允许插入多个null
*
* 迭代遍历List更倾向于用下标方式
*
* List提供了一个特殊的迭代器实现类ListIterator,额外允许插入替换和双向访问
*
* List接口还提供了搜索元素的方法,基于性能考虑,需要慎重使用
* 大部分都是线性时间复杂度
*
* 虽然允许列表将自己包含为元素,但此时equals和hashCode方法将不再在这样的列表上很好地定义
*/
public interface List<E> extends Collection<E> {
// Query Operations
/**
* 列表元素数目,不超过int最大值
*/
int size();
// 来自Collection
boolean isEmpty();
boolean contains(Object o);
Iterator<E> iterator();
Object[] toArray();
<T> T[] toArray(T[] a);
// Modification Operations
// 来自Collection
boolean add(E e);
boolean remove(Object o);
// Bulk Modification Operations
// 来自Collection
boolean containsAll(Collection<?> c);
boolean addAll(Collection<? extends E> c);
boolean addAll(int index, Collection<? extends E> c);
boolean removeAll(Collection<?> c);
boolean retainAll(Collection<?> c);
void clear();
default void replaceAll(UnaryOperator<E> operator) {
Objects.requireNonNull(operator);
final ListIterator<E> li = this.listIterator();
while (li.hasNext()) {
li.set(operator.apply(li.next()));
}
}
@SuppressWarnings({"unchecked", "rawtypes"})
default void sort(Comparator<? super E> c) {
Object[] a = this.toArray();
Arrays.sort(a, (Comparator) c);
ListIterator<E> i = this.listIterator();
for (Object e : a) {
i.next();
i.set((E) e);
}
}
// Comparison and hashing
boolean equals(Object o);
int hashCode();
// Positional Access Operations 指定位置访问操作:增删改查
E get(int index);
E set(int index, E element);
void add(int index, E element);
E remove(int index);
// Search Operations
/**
* 返回第一个o出现位置
*/
int indexOf(Object o);
/**
* 返回最后一个o出现位置
*/
int lastIndexOf(Object o);
// List Iterators
/**
* 返回java.util.ListIterator迭代器
*/
ListIterator<E> listIterator();
/**
* 返回游标在指定位置的java.util.ListIterator迭代器
*/
ListIterator<E> listIterator(int index);
// View
/**
* 返回List指定范围的子列表
*/
List<E> subList(int fromIndex, int toIndex);
@Override
default Spliterator<E> spliterator() {
return Spliterators.spliterator(this, Spliterator.ORDERED);
}
}
AbstractCollection
是实现了 Collection
接口的一个抽象类,主要是实现了部分方法,减少直接实现一个集合的难度,自定义一个集合仅仅需要实现 AbstractCollection
中的抽象方法即可,如果集合有自己特殊的行为,重写方法即可。源码如下,这些方法在 ArrayList
中都会出现,但实现方式肯定是有所改变的。
/**
* Collection接口的一个抽象实现类
* 如果实现一个不可修改的集合,子类还需要实现iterator()和size()方法
* 如果实现一个可修改的,子类还需要实现add()方法以及能remove的iterator
*/
public abstract class AbstractCollection<E> implements Collection<E> {
/**
* 唯一的构造函数
*/
protected AbstractCollection() {
}
// Query Operations
public abstract Iterator<E> iterator();
public abstract int size();
// 主要是利用size()和迭代器来默认实现下列方法
public boolean isEmpty() {
return size() == 0;
}
public boolean contains(Object o) {
Iterator<E> it = iterator();
if (o==null) {
while (it.hasNext())
if (it.next()==null)
return true;
} else {
while (it.hasNext())
if (o.equals(it.next()))
return true;
}
return false;
}
public Object[] toArray() {
// Estimate size of array; be prepared to see more or fewer elements
Object[] r = new Object[size()];
Iterator<E> it = iterator();
for (int i = 0; i < r.length; i++) {
if (! it.hasNext()) // fewer elements than expected
return Arrays.copyOf(r, i);
r[i] = it.next();
}
return it.hasNext() ? finishToArray(r, it) : r;
}
public <T> T[] toArray(T[] a) {
// Estimate size of array; be prepared to see more or fewer elements
int size = size();
T[] r = a.length >= size ? a :
(T[])java.lang.reflect.Array
.newInstance(a.getClass().getComponentType(), size);
Iterator<E> it = iterator();
for (int i = 0; i < r.length; i++) {
if (! it.hasNext()) { // fewer elements than expected
if (a == r) {
r[i] = null; // null-terminate
} else if (a.length < i) {
return Arrays.copyOf(r, i);
} else {
System.arraycopy(r, 0, a, 0, i);
if (a.length > i) {
a[i] = null;
}
}
return a;
}
r[i] = (T)it.next();
}
// more elements than expected
return it.hasNext() ? finishToArray(r, it) : r;
}
/**
* 集合最大容量限制
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
/**
* Reallocates the array being used within toArray when the iterator
* returned more elements than expected, and finishes filling it from
* the iterator.
*
* @param r the array, replete with previously stored elements
* @param it the in-progress iterator over this collection
* @return array containing the elements in the given array, plus any
* further elements returned by the iterator, trimmed to size
*/
@SuppressWarnings("unchecked")
private static <T> T[] finishToArray(T[] r, Iterator<?> it) {
int i = r.length;
while (it.hasNext()) {
int cap = r.length;
if (i == cap) {
int newCap = cap + (cap >> 1) + 1;
// overflow-conscious code
if (newCap - MAX_ARRAY_SIZE > 0)
newCap = hugeCapacity(cap + 1);
r = Arrays.copyOf(r, newCap);
}
r[i++] = (T)it.next();
}
// trim if overallocated
return (i == r.length) ? r : Arrays.copyOf(r, i);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError
("Required array size too large");
return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
}
// Modification Operations
public boolean add(E e) {
throw new UnsupportedOperationException();
}
public boolean remove(Object o) {
Iterator<E> it = iterator();
if (o==null) {
while (it.hasNext()) {
if (it.next()==null) {
it.remove();
return true;
}
}
} else {
while (it.hasNext()) {
if (o.equals(it.next())) {
it.remove();
return true;
}
}
}
return false;
}
// Bulk Operations
public boolean containsAll(Collection<?> c) {
for (Object e : c)
if (!contains(e))
return false;
return true;
}
public boolean addAll(Collection<? extends E> c) {
boolean modified = false;
for (E e : c)
if (add(e))
modified = true;
return modified;
}
public boolean removeAll(Collection<?> c) {
Objects.requireNonNull(c);
boolean modified = false;
Iterator<?> it = iterator();
while (it.hasNext()) {
if (c.contains(it.next())) {
it.remove();
modified = true;
}
}
return modified;
}
public boolean retainAll(Collection<?> c) {
Objects.requireNonNull(c);
boolean modified = false;
Iterator<E> it = iterator();
while (it.hasNext()) {
if (!c.contains(it.next())) {
it.remove();
modified = true;
}
}
return modified;
}
public void clear() {
Iterator<E> it = iterator();
while (it.hasNext()) {
it.next();
it.remove();
}
}
/**
* 集合的打印方法
*/
public String toString() {
Iterator<E> it = iterator();
if (! it.hasNext())
return "[]";
StringBuilder sb = new StringBuilder();
sb.append('[');
for (;;) {
E e = it.next();
sb.append(e == this ? "(this Collection)" : e);
if (! it.hasNext())
return sb.append(']').toString();
sb.append(',').append(' ');
}
}
}
很明显,AbstractList
是对列表集合而言的一个抽象类,它属于集合所以继承自 AbstractCollection
,同时也要实现 List
接口。作为抽象类,主要是让各种列表类的实现便的简单快捷,面向对象的好处。
该抽象类的源码还包含了四个类,迭代器的实现类 Itr
和 ListItr
,子列表类 SubList
和支持随机访问的 RandomAccessSubList
。
/**
* 和其他抽象集合不同,不需要实现一个迭代器。该类中实现了迭代器以及列表迭代器
*/
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
protected AbstractList() {
}
// =========增删改查=========
/**
* 尝试尾插一个元素
*/
public boolean add(E e) {
add(size(), e);
return true;
}
abstract public E get(int index);
public E set(int index, E element) {
throw new UnsupportedOperationException();
}
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
public E remove(int index) {
throw new UnsupportedOperationException();
}
// 利用listIterator()返回的ListIterator迭代器进行查找
public int indexOf(Object o) {
ListIterator<E> it = listIterator();
if (o==null) {
while (it.hasNext())
if (it.next()==null)
return it.previousIndex();
} else {
while (it.hasNext())
if (o.equals(it.next()))
return it.previousIndex();
}
return -1;
}
public int lastIndexOf(Object o) {
ListIterator<E> it = listIterator(size());
if (o==null) {
while (it.hasPrevious())
if (it.previous()==null)
return it.nextIndex();
} else {
while (it.hasPrevious())
if (o.equals(it.previous()))
return it.nextIndex();
}
return -1;
}
// Bulk Operations
public void clear() {
removeRange(0, size());
}
public boolean addAll(int index, Collection<? extends E> c) {
rangeCheckForAdd(index);
boolean modified = false;
for (E e : c) {
add(index++, e);
modified = true;
}
return modified;
}
// Iterators
/**
* 返回一个迭代器
*/
public Iterator<E> iterator() {
return new Itr();
}
/**
* 返回一个列表迭代器
*/
public ListIterator<E> listIterator() {
return listIterator(0);
}
/**
* 返回一个指定位置的列表迭代器
*/
public ListIterator<E> listIterator(final int index) {
rangeCheckForAdd(index);
return new ListItr(index);
}
// 迭代器实现类
private class Itr implements Iterator<E> {
/**
* Index of element to be returned by subsequent call to next.
*/
int cursor = 0;
/**
* Index of element returned by most recent call to next or
* previous. Reset to -1 if this element is deleted by a call
* to remove.
*/
int lastRet = -1;
/**
* The modCount value that the iterator believes that the backing
* List should have. If this expectation is violated, the iterator
* has detected concurrent modification.
*/
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != size();
}
public E next() {
checkForComodification();
try {
int i = cursor;
E next = get(i);
lastRet = i;
cursor = i + 1;
return next;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
AbstractList.this.remove(lastRet);
if (lastRet < cursor)
cursor--;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException e) {
throw new ConcurrentModificationException();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
// ListIterator接口的实现类
private class ListItr extends Itr implements ListIterator<E> {
ListItr(int index) {
cursor = index;
}
public boolean hasPrevious() {
return cursor != 0;
}
public E previous() {
checkForComodification();
try {
int i = cursor - 1;
E previous = get(i);
lastRet = cursor = i;
return previous;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
public int nextIndex() {
return cursor;
}
public int previousIndex() {
return cursor-1;
}
public void set(E e) {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
AbstractList.this.set(lastRet, e);
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
public void add(E e) {
checkForComodification();
try {
int i = cursor;
AbstractList.this.add(i, e);
lastRet = -1;
cursor = i + 1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
}
/**
* 返回子列表,原列表是否支持随机访问决定子列表是否也支持
*/
public List<E> subList(int fromIndex, int toIndex) {
return (this instanceof RandomAccess ?
new RandomAccessSubList<>(this, fromIndex, toIndex) :
new SubList<>(this, fromIndex, toIndex));
}
// Comparison and hashing
/**
* 两个元素需要内容完全一样才相等
*/
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof List))
return false;
ListIterator<E> e1 = listIterator();
ListIterator<?> e2 = ((List<?>) o).listIterator();
while (e1.hasNext() && e2.hasNext()) {
E o1 = e1.next();
Object o2 = e2.next();
if (!(o1==null ? o2==null : o1.equals(o2)))
return false;
}
return !(e1.hasNext() || e2.hasNext());
}
/**
* hashCode和元素内容相关
*/
public int hashCode() {
int hashCode = 1;
for (E e : this)
hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
return hashCode;
}
/**
* 指定范围删除,利用ListIterator迭代器
*/
protected void removeRange(int fromIndex, int toIndex) {
ListIterator<E> it = listIterator(fromIndex);
for (int i=0, n=toIndex-fromIndex; i<n; i++) {
it.next();
it.remove();
}
}
/**
* 记录列表结构修改的次数
* 该成员主要被iterator和list iterator使用
* 如果该值没有按照预期进行变化,迭代器的next/remove/previous/set/add操作会抛出ConcurrentModificationException
* 迭代器实现fail-fast机制,就可以利用该成员
*/
protected transient int modCount = 0;
private void rangeCheckForAdd(int index) {
if (index < 0 || index > size())
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
private String outOfBoundsMsg(int index) {
return "Index: "+index+", Size: "+size();
}
}
// 定义了SubList类
class SubList<E> extends AbstractList<E> {
private final AbstractList<E> l;
private final int offset;
private int size;
SubList(AbstractList<E> list, int fromIndex, int toIndex) {
if (fromIndex < 0)
throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
if (toIndex > list.size())
throw new IndexOutOfBoundsException("toIndex = " + toIndex);
if (fromIndex > toIndex)
throw new IllegalArgumentException("fromIndex(" + fromIndex +
") > toIndex(" + toIndex + ")");
l = list;
offset = fromIndex;
size = toIndex - fromIndex;
this.modCount = l.modCount;
}
public E set(int index, E element) {
rangeCheck(index);
checkForComodification();
return l.set(index+offset, element);
}
public E get(int index) {
rangeCheck(index);
checkForComodification();
return l.get(index+offset);
}
public int size() {
checkForComodification();
return size;
}
public void add(int index, E element) {
rangeCheckForAdd(index);
checkForComodification();
l.add(index+offset, element);
this.modCount = l.modCount;
size++;
}
public E remove(int index) {
rangeCheck(index);
checkForComodification();
E result = l.remove(index+offset);
this.modCount = l.modCount;
size--;
return result;
}
protected void removeRange(int fromIndex, int toIndex) {
checkForComodification();
l.removeRange(fromIndex+offset, toIndex+offset);
this.modCount = l.modCount;
size -= (toIndex-fromIndex);
}
public boolean addAll(Collection<? extends E> c) {
return addAll(size, c);
}
public boolean addAll(int index, Collection<? extends E> c) {
rangeCheckForAdd(index);
int cSize = c.size();
if (cSize==0)
return false;
checkForComodification();
l.addAll(offset+index, c);
this.modCount = l.modCount;
size += cSize;
return true;
}
public Iterator<E> iterator() {
return listIterator();
}
public ListIterator<E> listIterator(final int index) {
checkForComodification();
rangeCheckForAdd(index);
return new ListIterator<E>() {
private final ListIterator<E> i = l.listIterator(index+offset);
public boolean hasNext() {
return nextIndex() < size;
}
public E next() {
if (hasNext())
return i.next();
else
throw new NoSuchElementException();
}
public boolean hasPrevious() {
return previousIndex() >= 0;
}
public E previous() {
if (hasPrevious())
return i.previous();
else
throw new NoSuchElementException();
}
public int nextIndex() {
return i.nextIndex() - offset;
}
public int previousIndex() {
return i.previousIndex() - offset;
}
public void remove() {
i.remove();
SubList.this.modCount = l.modCount;
size--;
}
public void set(E e) {
i.set(e);
}
public void add(E e) {
i.add(e);
SubList.this.modCount = l.modCount;
size++;
}
};
}
public List<E> subList(int fromIndex, int toIndex) {
return new SubList<>(this, fromIndex, toIndex);
}
private void rangeCheck(int index) {
if (index < 0 || index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
private void rangeCheckForAdd(int index) {
if (index < 0 || index > size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
private String outOfBoundsMsg(int index) {
return "Index: "+index+", Size: "+size;
}
private void checkForComodification() {
if (this.modCount != l.modCount)
throw new ConcurrentModificationException();
}
}
// 定义了RandomAccessSubList类
class RandomAccessSubList<E> extends SubList<E> implements RandomAccess {
RandomAccessSubList(AbstractList<E> list, int fromIndex, int toIndex) {
super(list, fromIndex, toIndex);
}
public List<E> subList(int fromIndex, int toIndex) {
return new RandomAccessSubList<>(this, fromIndex, toIndex);
}
}
有了上面的铺垫,下面就可以直接进入 ArrayList
源码去研究了。为了减小篇幅,删除了1.8新特性后引入的代码。
package java.util;
/**
* 该实现类允许存入任意元素,包括null
* 大致上等同于Vector类,只是线程不安全
*
* 在添加大量元素前,可以使用ensureCapacity()来增加容量,以此减少扩容次数
*
* 可以利用Collections.synchronizedList(new ArrayList(...))进行同步
*
* 此类的iterator()和listIterator()方法返回的迭代器是fail-fast的:在创建迭代器之后,除非通过迭代器自身的remove或add方法从结构上对列表进行修改,否则在任何时间以任何方式对列表进行修改,迭代器都会抛出ConcurrentModificationException。因此,面对并发的修改,迭代器很快就会完全失败,而不是冒着在将来某个不确定时间发生任意不确定行为的风险。
*
* jdk1.8源码
*/
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
private static final long serialVersionUID = 8683452581122892189L;
/**
* 默认初始容量大小为10
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* 静态初始化的空数组 (用于空实例的赋值)
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
* 默认大小(10)的空数组
* 把它和EMPTY_ELEMENTDATA数组中区分开,因为在添加第一个元素时容量会增加
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* 保存ArrayList数据的数组
* 任何一个空ArrayList(elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)将在第一个元素加入时容量扩展至DEFAULT_CAPACITY
* 非私有方便嵌套类访问,transient表示不参与序列化,因为elementData往往除了真正的数据还有冗余
*/
transient Object[] elementData; // non-private to simplify nested class access
/**
* 包含的元素个数
*/
private int size;
/**
* 初始化一个initialCapacity大小的空ArrayList.
* @throws initialCapacity小于0抛出IllegalArgumentException
*/
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
}
}
/**
* 默认构造函数,DEFAULTCAPACITY_EMPTY_ELEMENTDATA初始其实是空数组,当添加第一个元素的时候数组容量才变成默认值10
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
/**
* 构造一个包含指定集合的元素的ArrayList
*/
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray 可能返回的不是Object类型的数组所以加上判断
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// 如果指定集合为空,那么用EMPTY_ELEMENTDATA赋值
this.elementData = EMPTY_ELEMENTDATA;
}
}
/**
* 修改ArrayList实例的容量是列表的当前大小,使用此方法来去除elementData的冗余
*/
public void trimToSize() {
modCount++;
if (size < elementData.length) {
elementData = (size == 0)
? EMPTY_ELEMENTDATA
: Arrays.copyOf(elementData, size);
}
}
/**
* 扩容ArrayList
* 确保elementData至少能容纳minCapacity数量的元素
*/
public void ensureCapacity(int minCapacity) {
int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
// any size if not default element table
? 0
// larger than default for default empty table. It's already
// supposed to be at default size.
: DEFAULT_CAPACITY;
if (minCapacity > minExpand) {
ensureExplicitCapacity(minCapacity);
}
}
// 得到最小扩容量
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
// 如果minCapacity比elementData容量大,需要调用grow()方法扩容
private void ensureExplicitCapacity(int minCapacity) {
// 将“修改统计数”+1
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
/**
* 数组最大容量 2^31-9
* 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;
/**
* 扩容(超过minCapacity)
* minCapacity小于0会在hugeCapacity方法中抛出OutOfMemoryError
*/
private void grow(int minCapacity) {
// oldCapacity为旧容量,newCapacity为新容量
int oldCapacity = elementData.length;
// 将oldCapacity 右移一位,其效果相当于oldCapacity / 2
// 位运算的速度远远快于整除运算,结果就是将新容量更新为旧容量的1.5倍
// jdk1.6是newCapacity = (oldCapacity * 3)/2 + 1;
int newCapacity = oldCapacity + (oldCapacity >> 1);
// 然后检查新容量是否大于最小需要容量
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
// 再检查新容量是否超出了ArrayList所定义的最大容量
// 若超出了,则调用hugeCapacity()来比较minCapacity和 MAX_ARRAY_SIZE
// // 如果minCapacity大于MAX_ARRAY_SIZE,则新容量则为Interger.MAX_VALUE,否则,新容量大小则为 MAX_ARRAY_SIZE
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
// 比较minCapacity和MAX_ARRAY_SIZE
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // 溢出了
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
/**
* 返回列表中的元素数
*/
public int size() {
return size;
}
/**
* 列表是否为空
*/
public boolean isEmpty() {
return size == 0;
}
/**
* 通过indexOf()方法判断列表是否包含指定的元素
*/
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
/**
* 遍历方法返回列表中指定元素首次出现的索引下标,如果列表不包含此元素,则为-1
*/
public int indexOf(Object o) {
// 能够通过遍历查找是否含有null的元素
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
/**
* 返回此列表中指定元素的最后一次出现的索引,如果此列表不包含元素,则返回-1
*/
public int lastIndexOf(Object o) {
// 倒序遍历方式实现
if (o == null) {
for (int i = size-1; i >= 0; i--)
if (elementData[i]==null)
return i;
} else {
for (int i = size-1; i >= 0; i--)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
/**
* 返回此ArrayList实例的浅拷贝(元素本身不被复制)
*/
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);
}
}
/**
* 以正确的顺序(从第一个到最后一个元素)返回一个包含此列表中所有元素的数组
* 返回的数组将是“安全的”,因为该列表不保留对它的引用(换句话说,这个方法必须分配一个新的数组)
* 因此,调用者可以自由地修改返回的数组,不会影响列表
* 将列表转为数组调用此方法会导致泛型丢失
*/
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}
/**
* 以正确的顺序返回一个包含此列表中所有元素的数组
* 返回的数组的运行时类型是指定数组的运行时类型
* 如果入参a数组的大小足够容纳列表的size,则列表的数据直接复制进入a数组即可
* 如果a数组容量不够,则需要开辟新数组,复制完成后返回新数组,而a数组还是原来的样子
*
* 性能方面:只有a数组的大小正好是列表的size,性能最优(参考《码出高效》P166)
*/
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
if (a.length < size)
// 新建一个运行时类型的数组,拷贝elementData数组的内容
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
// 调用System提供的arraycopy()方法实现数组之间的复制
System.arraycopy(elementData, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
// Positional Access Operations
@SuppressWarnings("unchecked")
E elementData(int index) {
return (E) elementData[index];
}
/**
* 返回此列表中指定位置的元素
*/
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
/**
* 用指定的元素替换此列表中指定位置的元素
* 返回旧元素
*/
public E set(int index, E element) {
rangeCheck(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
/**
* 将指定的元素追加到此列表的末尾(尾插)
*/
public boolean add(E e) {
ensureCapacityInternal(size + 1); // 修改计数器加1
// 这里看到ArrayList添加元素的实质就相当于为数组赋值
elementData[size++] = e;
return true;
}
/**
* 在列表中的指定位置插入指定的元素
* 从index开始之后的所有成员后移一个位置,将element插入index位置,最后size加1
*/
public void add(int index, E element) {
// 先对index进行界限检查
rangeCheckForAdd(index);
// 保证capacity足够大
ensureCapacityInternal(size + 1); // Increments modCount!!
// index开始之后的所有成员后移一个位置
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
/**
* 删除列表中指定位置的元素,并返回删除的元素
* 后续元素移动到左侧,数组中删除的元素位置会变为null
*/
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; // 置为null便于GC
// 返回删除的元素
return oldValue;
}
/**
* 从列表中删除指定元素的第一个出现;如果列表不包含该元素,则它不会更改
* 可以删除null
*/
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
/*
* 快速删除指定位置元素(数组左移)
*/
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
}
/**
* 删除所有元素,elementData并不会缩容
*/
public void clear() {
modCount++;
// clear to let GC do its work
for (int i = 0; i < size; i++)
elementData[i] = null;
size = 0;
}
/**
* 按指定集合的Iterator返回的顺序将指定集合中的所有元素追加到列表的末尾
*/
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;
}
/**
* 从指定的位置开始,将指定集合中的所有元素插入到此列表中
*/
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;
}
/**
* 从此列表中删除所有索引为fromIndex(含)和toIndex之间的元素
*/
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;
}
/**
* 检查给定的索引是否在范围内
* 不需要检查是否为负数,因为访问数组时下标为负会抛出ArrayIndexOutOfBoundsException
* 大于等于size,因为elementData实际大小很大可能没有问题
*/
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
/**
* add和addAll方法中使用,对index进行界限检查
*/
private void rangeCheckForAdd(int index) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
/**
* 返回IndexOutOfBoundsException细节信息
*/
private String outOfBoundsMsg(int index) {
return "Index: "+index+", Size: "+size;
}
/**
* 从列表中删除指定集合中包含的所有元素
*/
public boolean removeAll(Collection<?> c) {
Objects.requireNonNull(c); // 判空
return batchRemove(c, false);
}
/**
* 仅保留此列表中包含在指定集合中的元素
*/
public boolean retainAll(Collection<?> c) {
Objects.requireNonNull(c);
return batchRemove(c, true);
}
// 批量删除元素,complement表示删除c含有的元素还是只保留c含有的元素
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 {
// 如果上面删除操作中间发生异常,则把剩下未操作完的继续赋值
if (r != size) {
System.arraycopy(elementData, r, elementData, w, size - r);
w += size - r;
}
if (w != size) {
// clear to let GC do its work
for (int i = w; i < size; i++)
elementData[i] = null;
modCount += size - w;
size = w;
modified = true;
}
}
return modified;
}
/**
* 列表序列化时调用,写入流中
*/
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException{
// Write out element count, and any hidden stuff
int expectedModCount = modCount;
s.defaultWriteObject();
// 写入真实数据个数
s.writeInt(size);
// 写入“数组的每一个元素”
for (int i=0; i<size; i++) {
s.writeObject(elementData[i]);
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
/**
* 反序列化时调用
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
elementData = EMPTY_ELEMENTDATA;
// Read in size, and any hidden stuff
s.defaultReadObject();
// 从输入流中读取ArrayList的“容量”
s.readInt(); // ignored
if (size > 0) {
// be like clone(), allocate array based upon size not capacity
ensureCapacityInternal(size);
Object[] a = elementData;
// 从输入流中将“所有的元素值”读出
for (int i=0; i<size; i++) {
a[i] = s.readObject();
}
}
}
/**
* 从列表中的指定位置开始,返回列表中的元素的列表迭代器
* 指定的索引表示初始调用将返回的第一个元素为next
* 初始调用previous将返回指定索引减1的元素
* 返回的列表迭代器是fail-fast
*/
public ListIterator<E> listIterator(int index) {
if (index < 0 || index > size)
throw new IndexOutOfBoundsException("Index: "+index);
return new ListItr(index);
}
/**
* 返回列表中的列表迭代器
* 返回的列表迭代器是fail-fast
*/
public ListIterator<E> listIterator() {
return new ListItr(0);
}
/**
* 以正确的顺序返回该列表中的元素的迭代器
* 返回的迭代器是fail-fast
*/
public Iterator<E> iterator() {
return new Itr();
}
/**
* AbstractList.Itr的优化版本
*/
private class Itr implements Iterator<E> {
int cursor; // 一个游标,指向下一个将要返回的元素的下标
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
// 判断cursor和size是否相等,返回true或false
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
// 首先检查modCount 和 expectedModCount是否相等,如果不相等,抛出异常
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1; // 更新游标指向下一个元素
return (E) elementData[lastRet = i];
}
// 删除上一次访问的元素
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet; // 游标后退一次
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
@Override
@SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> consumer) {
Objects.requireNonNull(consumer);
final int size = ArrayList.this.size;
int i = cursor;
if (i >= size) {
return;
}
final Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length) {
throw new ConcurrentModificationException();
}
while (i != size && modCount == expectedModCount) {
consumer.accept((E) elementData[i++]);
}
// update once at end of iteration to reduce heap write traffic
cursor = i;
lastRet = i - 1;
checkForComodification();
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
/**
* An optimized version of AbstractList.ListItr
* ListIterator在Iterator的基础上增加了添加对象,修改对象,逆向遍历等方法,这些是Iterator不能实现的
*/
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();
}
}
}
/**
* 返回指定范围的元素集合,参数含头不含尾.
*
* 子列表的修改会导致原列表的修改
* For example, the following idiom removes a range of elements from a list:
*
* list.subList(from, to).clear();
*
*
* 原列表的修改会导致子列表增删改查抛出异常——fail-fast机制
*
* 返回类型为SubList,ArrayList的内部类,继承自AbstractList
*/
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size);
return new SubList(this, 0, fromIndex, toIndex);
}
// 检查范围是否合法
static void subListRangeCheck(int fromIndex, int toIndex, int size) {
if (fromIndex < 0)
throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
if (toIndex > size)
throw new IndexOutOfBoundsException("toIndex = " + toIndex);
if (fromIndex > toIndex)
throw new IllegalArgumentException("fromIndex(" + fromIndex +
") > toIndex(" + toIndex + ")");
}
// SubList实现了RandomAccess接口,并不能序列化
private class SubList extends AbstractList<E> implements RandomAccess {
// ArrayList的subList()方法会将列表传入SubList,所以子列表操作会影响原列表
private final AbstractList<E> parent;
private final int parentOffset;
private final int offset;
int size;
SubList(AbstractList<E> parent, int offset, int fromIndex, int toIndex) {
this.parent = parent;
this.parentOffset = fromIndex;
this.offset = offset + fromIndex;
this.size = toIndex - fromIndex;
this.modCount = ArrayList.this.modCount;
}
public E set(int index, E e) {
rangeCheck(index);
checkForComodification();
E oldValue = ArrayList.this.elementData(offset + index);
ArrayList.this.elementData[offset + index] = e;
return oldValue;
}
public E get(int index) {
rangeCheck(index);
checkForComodification();
return ArrayList.this.elementData(offset + index);
}
public int size() {
checkForComodification();
return this.size;
}
public void add(int index, E e) {
rangeCheckForAdd(index);
checkForComodification();
parent.add(parentOffset + index, e);
this.modCount = parent.modCount;
this.size++;
}
public E remove(int index) {
rangeCheck(index);
checkForComodification();
E result = parent.remove(parentOffset + index);
this.modCount = parent.modCount;
this.size--;
return result;
}
protected void removeRange(int fromIndex, int toIndex) {
checkForComodification();
parent.removeRange(parentOffset + fromIndex,
parentOffset + toIndex);
this.modCount = parent.modCount;
this.size -= toIndex - fromIndex;
}
public boolean addAll(Collection<? extends E> c) {
return addAll(this.size, c);
}
public boolean addAll(int index, Collection<? extends E> c) {
rangeCheckForAdd(index);
int cSize = c.size();
if (cSize==0)
return false;
checkForComodification();
parent.addAll(parentOffset + index, c);
this.modCount = parent.modCount;
this.size += cSize;
return true;
}
public Iterator<E> iterator() {
return listIterator();
}
public ListIterator<E> listIterator(final int index) {
checkForComodification();
rangeCheckForAdd(index);
final int offset = this.offset;
return new ListIterator<E>() {
int cursor = index;
int lastRet = -1;
int expectedModCount = ArrayList.this.modCount;
public boolean hasNext() {
return cursor != SubList.this.size;
}
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= SubList.this.size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (offset + i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[offset + (lastRet = i)];
}
public boolean hasPrevious() {
return cursor != 0;
}
@SuppressWarnings("unchecked")
public E previous() {
checkForComodification();
int i = cursor - 1;
if (i < 0)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (offset + i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i;
return (E) elementData[offset + (lastRet = i)];
}
public int nextIndex() {
return cursor;
}
public int previousIndex() {
return cursor - 1;
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
SubList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = ArrayList.this.modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
public void set(E e) {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.set(offset + lastRet, e);
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
public void add(E e) {
checkForComodification();
try {
int i = cursor;
SubList.this.add(i, e);
cursor = i + 1;
lastRet = -1;
expectedModCount = ArrayList.this.modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
final void checkForComodification() {
if (expectedModCount != ArrayList.this.modCount)
throw new ConcurrentModificationException();
}
};
}
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size);
return new SubList(this, offset, fromIndex, toIndex);
}
private void rangeCheck(int index) {
if (index < 0 || index >= this.size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
private void rangeCheckForAdd(int index) {
if (index < 0 || index > this.size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
private String outOfBoundsMsg(int index) {
return "Index: "+index+", Size: "+this.size;
}
private void checkForComodification() {
if (ArrayList.this.modCount != this.modCount)
throw new ConcurrentModificationException();
}
}
}
常用方式,性能低一点
Integer[] integer = arrayList.toArray(new Integer[0]);
性能高,但得写两行
Integer[] integer1 = new Integer[arrayList.size()];
arrayList.toArray(integer1);
固定size通过下标删除
for (int i = 0,size = list.size(); i < size; i++) {
if (条件)
list.remove(i);
}
这种遍历删除,由于列表在删除的过程中 size 是更新的,后面继续遍历必然会发生越界。
更新size通过下标删除
for (int i = 0; i < list.size(); i++) {
if (条件)
list.remove(i);
}
这种方式虽然不会报错,但额外需要每次都计算一下 list.size()
。此外,还会带来删除错误问题,看下面的示例。具体原因相信参考 remove()
方法的过程就知道了。
ArrayList<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 5, 6, 3, 2));
for (int i = 0; i < list.size(); i++) {
if (list.get(i) > 4)
list.remove(i);
}
System.out.println(list);
// 输出: [1, 2, 3, 6, 3, 2]
完全利用迭代器遍历与删除
for (Iterator<T> ite = list.iterator(); ite.hasNext(); ) {
if (条件) {
ite.remove();
}
}
这种方式是没有问题的,因为迭代器维护了游标。我们再单独看一下 ArrayList.Ltr
中的 remove()
方法。
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();
}
}
其中包含了游标后退到上一次访问位置 (lastRet) 的代码,所以利用迭代器遍历删除没有问题。
迭代器遍历List进行删除
刚才是利用迭代器的 remove()
方法进行删除元素的,如果像下面这样利用列表的删除方法则又会产生问题。
for (Iterator<T> ite = list.iterator(); ite.hasNext(); ) {
if (条件) {
list.remove(ite.next());
}
}
例如下面代码:
ArrayList<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 5, 6, 3, 2));
for (Iterator<Integer> ite = list.iterator(); ite.hasNext(); ) {
Integer num = ite.next();
if (num > 4) {
list.remove(num);
}
}
System.out.println(list);
同样,对于Java的 foreach
语法糖,其本质也是迭代器,所以下面这种方式也是抛出相同的异常。
for (Integer num : list) {
if (num > 4) {
list.remove(num);
}
}
那么为什么会报出并发修改异常呢?
我们如果 debug 这段代码会发现,元素 5 是正常删除的,而在迭代器调用 next()
去获得元素 6 时发生异常,查看迭代器的 next()
方法。
public E next() {
// 首先检查modCount 和 expectedModCount是否相等,如果不相等,抛出异常
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];
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
可以断定,引起异常的原因是 modCount != expectedModCount
。expectedModCount
是 Itr
的成员变量,在 List
调用 iterator()
方法时会初始化成 List
此时的 modCount
。当第一次调用 list.remove(num)
方法时, modCount
加1,而 Itr
迭代器实例的 expectedModCount
没有变化,所以在 next()
方法中发现两者不等的时候,抛出异常。简单的来说,就是迭代器在操作列表,列表本身也在操作列表,不允许并发修改。
迭代器的 remove()
方法本质上还是调用的是 List
的 remove()
方法,为什么没问题呢?因为方法中最后还更新了 expectedModCount
。
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet; // 游标后退一次
lastRet = -1;
expectedModCount = modCount; // 更新expectedModCount
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}