一、简介
上图为ArrayList的继承树,可看出实现了四个接口,分别介绍一下:
- Serializable:是一个空接口,实现了该接口的类可序列化和反序列化
- Cloneable:是一个空接口,实现该接口的类覆盖了clone()方法,表明该类的实例对象能被克隆
- RandomAccess:是一个空接口,表明该类的实例对象支持随机访问
- List:表明该类是一个列表,具有增加、删除、修改、遍历等功能
二、源码分析
1. ArrayList的属性
// 默认初始化容量为10
private static final int DEFAULT_CAPACITY = 10;
// 空数组实例
private static final Object[] EMPTY_ELEMENTDATA = {};
// 当使用默认初始化容量时创建的空数组实例
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
// 存放元素的数组
// 当 elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
// 将第一个元素存入ArrayList时该数组会扩容至容量为10
transient Object[] elementData;
// ArrayList的实际大小,即存放的元素数量
private int size;
// ArrayList允许存放的最大元素数
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
2. 构造方法
// 默认构造函数,使用默认初始化容量10,存放元素的数组指向一个空数组,
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
// 传入一个初始化容量值,将存放元素的数组大小设置为该值
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(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// 集合非空时则将集合的元素复制至数组
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// 传入的集合为空时指向一个空数组
this.elementData = EMPTY_ELEMENTDATA;
}
}
3. 增加元素
// 将元素添加到数组末尾
public boolean add(E e) {
ensureCapacityInternal(size + 1); // 判断是否需要扩容,后面详细讲
elementData[size++] = e;
return true;
}
// 将元素添加到指定位置
public void add(int index, E element) {
rangeCheckForAdd(index); // 检查是否越界
ensureCapacityInternal(size + 1);
System.arraycopy(elementData, index, elementData, index + 1,
size - index); // 将index开始的元素向后移一位
elementData[index] = element;
size++;
}
// 将集合所有元素添加至列表末尾
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;
}
5. 删除元素
// 将指定位置的元素删除
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;
return oldValue;
}
// 删除指定元素
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;
}
// 删除指定范围的元素
protected void removeRange(int fromIndex, int toIndex) {
modCount++;
int numMoved = size - toIndex;
System.arraycopy(elementData, toIndex, elementData, fromIndex,
numMoved);
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); // 检查集合是否为null
return batchRemove(c, false);
}
// 按指定条件删除元素
@Override
public boolean removeIf(Predicate<? super E> filter) {
Objects.requireNonNull(filter);
int removeCount = 0; // 删除元素的个数
final BitSet removeSet = new BitSet(size); // 记录删除元素的位置
final int expectedModCount = modCount;
final int size = this.size;
for (int i=0; modCount == expectedModCount && i < size; i++) {
@SuppressWarnings("unchecked")
final E element = (E) elementData[i];
if (filter.test(element)) { // 检验元素是否符合删除条件
removeSet.set(i); // 将符合条件的元素在removeSet中对应的位置置true
removeCount++;
}
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
final boolean anyToRemove = removeCount > 0; // 是否有元素被删除
if (anyToRemove) { // 若为true则将数组中符合条件的元素删除
final int newSize = size - removeCount;
for (int i=0, j=0; (i < size) && (j < newSize); i++, j++) {
i = removeSet.nextClearBit(i);
elementData[j] = elementData[i];
}
for (int k=newSize; k < size; k++) {
elementData[k] = null;
}
this.size = newSize;
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
modCount++;
}
return anyToRemove;
}
// 删除所有元素
public void clear() {
modCount++;
for (int i = 0; i < size; i++)
elementData[i] = null;
size = 0;
}
6. 修改元素
// 修改指定位置的元素,并返回旧值
public E set(int index, E element) {
rangeCheck(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
7. 获取元素
// 获取指定位置的元素
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
E elementData(int index) {
return (E) elementData[index];
}
8. 扩容机制
// 当尝试增加一个元素时,会调用该函数
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
// elementData:存储元素的数组
// minCapacity:增加元素后数组的总大小
// 该方法用来计算并返回增加元素后数组的大小
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
// 决定是否扩容,
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// 若增加元素后数组大小大于原数组大小则需要扩容
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
// 扩容至原数组大小的1.5倍
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // 上溢
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
- 计算增加元素后元素的个数:当增加元素时,会先调用方法计算增加元素后元素的个数,分为两种情况,若数组为空则取初始化容量和增加元素后元素个数的最大值,否则直接返回增加元素后元素个数
- 判断是否扩容:根据返回值,如果大于当前数组的容量则需要扩容
- 扩容:新的容量为原来的1.5倍,若该值小于元素个数则新容量更改为元素个数,若大于MAX_ARRAY_SIZE则取Integer允许的最大值和MAX_ARRAY_SIZE的最大值,若小于0即上溢,抛出异常
- 复制元素至扩容后的数组