前言
本文主要针对 JDK1.8 的 ArrayList
源码进行解析,主要看源码注释,代码说明了全部实现细节。
I. 继承结构
ArrayList
的继承结构如下图所示,下面我们进行一一解析。
Serializable
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
RandomAccess
接口是标记接口,内容为空。该标记接口表示该集合支持随机访问,接口定义如下:
public interface RandomAccess {
}
ArrayList
实现 RandomAccess
接口,LinkedList
并没有实现 RandomAccess
接口,随机访问影响我们在遍历列表的时候是用下标的方式还是迭代器的方式,从性能上看 对于支持快速随机访问的集合,下标的方式更快,迭代器较慢;不支持快速随机访问的集合,迭代器更快,下标的方式很慢。
那么如何判断一个集合是否支持随机访问呢?
通过 instanceof
判断集合是否实现了 RandomAccess
接口。
具体可参考:https://blog.csdn.net/weixin_39148512/article/details/79234817
Cloneable
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
Iterable
一个集类要表明自己支持迭代,能有使用 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
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
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
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()))</