系列文章:
前言
本文开始分析具体集合的源码和实现原理,首先来看ArrayList
。ArrayList
可以理解为一个动态数组,与普通数组相比,它的容量能动态增长。其定义如下:
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
可以看到ArrayList
继承了AbstractList
类,实现了List
,RandomAccess
,Cloneable
和java.io.Serializable
四个接口。
上文提到,AbstractList
类提供了大部分List接口的实现,帮助我们减少了实现List接口的工作。
RandomAccess
接口是List实现所使用的标记接口,表明List支持快速随机访问功能(就是通过索引获取元素)。
实现Cloneable
接口表明覆盖了Clone()
函数,能被克隆,实现java.io.Serializable
接口表明ArrayList
支持序列化。
本文源码分析基于jdk 1.8.0_121
继承关系
ArrayList的继承关系
java.lang.Object
|___java.util.AbstractCollection<E>
|___ java.util.AbstractList<E>
|___ java.util.ArrayList<E>
所有已实现的接口:
Serializable, Cloneable, Iterable<E>, Collection<E>, List<E>, RandomAccess
直接已知子类:
AttributeList, RoleList, RoleUnresolvedList
关系图
ArrayList的两个成员elementData
和size
比较重要:
-
elementData
是Object
类型的数组,保存了ArrayList
的数据,是ArrayList
的底层实现,它是个动态数组,在添加数据过程中不断扩展容量,最大容量为Integer.MAX_VALUE - 8
;容量的增长方式在源码中具体再分析 -
size
是当前动态数组的实际大小
构造函数
public ArrayList() {} // 默认构造函数
public ArrayList(int initialCapacity) {} // 构造一个具有特定初始容量的ArrayList
public ArrayList(Collection<? extends E> c) {} // 创建一个包含Collection的ArrayList
以上三种构造函数在不同JDK版本之间也略有差异,但思想或者做的工作都基本一致。
public ArrayList()
在JDK1.8.0_121
中令elementData
为一个空数组DEFAULTCAPACITY_EMPTY_ELEMENTDATA
,而此版本中还存在另一个空数组成员EMPTY_ELEMENTDATA
,此两者的区别是用来区分ArrayList
添加第一个元素时容量要扩张多少。在之前的JDK版本中默认构造函数是直接初始化一个容量为10的数组。 (具体哪一版本开始出现这一区别不知道)
public ArrayList(int initialCapacity)
构造一个指定初始容量的空列表,当initialCapacity
为0时,令elementData
为EMPTY_ELEMENTDATA
。
public ArrayList(Collection<? extends E> c)
构造一个包含Collection
的元素的列表,这些元素按照该Collection
的迭代器返回它们的顺序排列的,先将Collection
转为数组,再将数组拷贝给elementData
。
API
// Collection中定义的API(部分)
boolean add(E object)
boolean addAll(Collection<? extends E> collection)
void clear()
boolean contains(Object object)
boolean containsAll(Collection<?> collection)
boolean equals(Object object)
int hashCode()
boolean isEmpty()
Iterator<E> iterator()
boolean remove(Object object)
boolean removeAll(Collection<?> collection)
boolean retainAll(Collection<?> collection)
int size()
<T> T[] toArray(T[] array)
Object[] toArray()
// AbstractList API(部分)
void add(int index, E element)
boolean addAll(int index, Collection<? extends E> c)
E get(int index)
int indexOf(Object o)
ListIterator<E> listIterator()
ListIterator<E> listIterator(final int index)
E remove(int index)
E set(int index, E element)
List<E> subList(int fromIndex, int toIndex)
// ArrayList API(部分)
Object clone()
void ensureCapacity(int minCapacity)
void trimToSize()
void removeRange(int fromIndex, int toIndex)
源码分析
成员对象
// List默认容量
private static final int DEFAULT_CAPACITY = 10;
// 空数组
private static final Object[] EMPTY_ELEMENTDATA = {};
// 空数组,使用默认构造函数创建,则默认对象内容默认是该值
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
// 保存ArrayList中数据的数组,transient表示不参与序列化
transient Object[] elementData;
// 实际容量大小
private int size;
// 数组最大值
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
构造函数
// 带初始容量的构造函数
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);
}
}
// 默认构造函数
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
// 带Collection对象的构造函数
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
改变容量值
// 将当前容量值设置为实际元素个数
public void trimToSize() {
modCount++;
if (size < elementData.length) {
elementData = (size == 0)
? EMPTY_ELEMENTDATA
: Arrays.copyOf(elementData, size);
}
}
确定容量
// 判断待设置的最小容量minCapacity和默认容量大小
// minCapacity大于minExpand时才扩张容量
public void ensureCapacity(int minCapacity) {
int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)? 0: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);
}
// 修改次数+1,如果minCapacity大于数组长度,则扩张容量
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
// 设置新容量为(原始容量x3)/2
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
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超出Integer.MAX_VALUE时,minCapacity变为负数,抛出异常
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
增加元素
// 添加元素e到ArrayList
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
// 添加元素到指定位置
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1); // Increments modCount!!
// 把原数组index索引开始后的所有元素向后移动一个位置
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
// 集合c追加到ArrayList中
public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityInternal(size + numNew); // Increments modCount
// 将集合c转换为数组后复制到elementData中
System.arraycopy(a, 0, elementData, size, numNew);
size += numNew;
return numNew != 0;
}
// 从位置index开始,将集合c添加到ArrayList中
public boolean addAll(int index, Collection<? extends E> c) {
rangeCheckForAdd(index);
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityInternal(size + numNew); // Increments modCount
int numMoved = size - index;
// 先在elementData中空出长度为集合c中元素个数的位置
if (numMoved > 0)
System.arraycopy(elementData, index, elementData, index + numNew,
numMoved);
// 复制集合元素到elementData中
System.arraycopy(a, 0, elementData, index, numNew);
size += numNew;
return numNew != 0;
}
toArray
// 转化为ArrayList的Object数组
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}
// 返回T类型的数组
public <T> T[] toArray(T[] a) {
// 如果数组a的大小小于ArrayList的实际大小
// 则新建一个数组(T[])数组,将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;
}
调用toArray
方法有以下两种:
java.lang.Integer[] obj = (java.lang.Integer[])list.toArray();
java.lang.Integer[] obj1 = list.toArray(new Integer[0]);
调用第一种方法会抛出“java.lang.ClassCastException
”异常,调用 toArray(T[] contents)
能正常返回 T[]
。
这是因为将Object[]
转换为的Integer[]
则会抛出“java.lang.ClassCastException
”异常,因为Java不支持向下转型。
设置元素
// 设置index处元素值,并返回旧值
public E set(int index, E element) {
rangeCheck(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
读取元素
// 获取index位置的元素值
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
删除元素
// 删除index处元素,并返回
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
int numMoved = size - index - 1;
// 移动数组中元素位置,保证数组连续性
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
// 删除指定元素
public boolean remove(Object o) {
// 判断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++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
// 快速删除第index个元素
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
}
// 删除一定索引范围内元素值
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;
}
// 删除所有元素
public boolean removeAll(Collection<?> c) {
Objects.requireNonNull(c);
return batchRemove(c, false);
}
序列化
// 将ArrayList的“容量,所有的元素值”都写入到输出流中
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();
}
}
// 将ArrayList的“容量”读出,再将“所有的元素值”读出
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
elementData = EMPTY_ELEMENTDATA;
// Read in size, and any hidden stuff
s.defaultReadObject();
// 读出容量
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();
}
}
}
遍历方式
- 迭代器遍历,即通过Iterator遍历
Iterator iter = list.iterator();
while(iter.hasNext()) {
iter.next();
}
- 随机访问,索引值
for (int i=0; i<list.size(); i++) {
list.get(i);
}
- foreach循环
for (Integer integ:list) {
;
}
通过比较以上三种遍历方式,我们发现通过随机访问方式效率最高,而另两种方式效率都不高。