1、介绍
1、可扩容,允许存储任何元素,包括null。这个类提供了一些方法来操纵数组大小,大致相当于Vector类。
2、ArrayList的容量是表示存储数组元素的大小,容量至少大于列表大小,在容量不足时,会自动扩容至原来的1.5倍
3、在添加元素时会通过ensureCapacity方法来判断是否需要扩容,减少扩容的次数
4、ArrayList是线程不同步的,当多线程环境下,可以通过List list = Collections.SynchronizedList(new ArrayList(...));获取同步list
5、fail-fast机制,在遍历集合过程中,使用list的增删方法,会抛出 ConcurrentModifyException 异常,是因为迭代时调用next方法时会判断
list中的modCount的值是否与内部类Itr对象中expectedCount的一致,不一致则抛出ConcurrentModifyException。list中的增删方法都会对modCount加1
6、listIterator不仅可以向后迭代,也可以向前迭代
2、类继承图
1)实现Cloneable接口,支持克隆,属于浅拷贝
2)实现Serializable接口,支持序列化传输
3)实现RandomAccess接口,支持随机访问(通过数组下标快速随机访问)
4)顶层接口是Iterable,列表元素可迭代。
3、核心源码解读
构造方法和默认初始容量
package java.util;import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import sun.misc.SharedSecrets;public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{private static final long serialVersionUID = 8683452581122892189L;// 默认初始容量为10private static final int DEFAULT_CAPACITY = 10;// 空数组用于空实例private static final Object[] EMPTY_ELEMENTDATA = {};// 当没有指定列表容量时,默认为空数组,当第一次添加元素时再根据实际情况判断// 使用默认的初始化容量还是最小所需容量private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};// ArrayList底层使用Object数组用来存储元素transient Object[] elementData; // non-private to simplify nested class access// 列表实际存储元素个数private int size;// 构造方法,给定初始化容量public ArrayList(int initialCapacity) {// 当给定初始化容量大于零时,按给定容量创建数组if (initialCapacity > 0) {this.elementData = new Object[initialCapacity];} else if (initialCapacity == 0) {// 当初始化容量为0时创建空数组this.elementData = EMPTY_ELEMENTDATA;} else {throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);}}// 构造器,没有给定默认初始化容量,创建默认空数组public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}// 构造方法,传入Collection对象,如果Collection对象的元素不为0// 复制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 boolean add(E e) {// 判断是否需要扩容并完成自动扩容ensureCapacityInternal(size + 1); // Increments modCount!!elementData[size++] = e;return true;
}private void ensureCapacityInternal(int minCapacity) {ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}private void ensureExplicitCapacity(int minCapacity) {// 新增元素modCount加1,用于元素迭代时fail-fast机制modCount++;// 最小所需容量是否大于当前数组长度,大于则需要扩容if (minCapacity - elementData.length > 0)grow(minCapacity);
}
调用grow方法自动扩容(minCapacity添加元素最小所需容量)
正常情况下扩容至原来的1.5倍,当扩容后的新容量大于MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8时,判断最小所需容量是否大于MAX_ARRAY_SIZE ,如果大于则使用Integer最大值,否则使用MAX_ARRAY_SIZE
private void grow(int minCapacity) {// 旧容量int oldCapacity = elementData.length;// 新容量扩容至原来容量的1.5倍(oldCapacity + oldCapacity/2)int newCapacity = oldCapacity + (oldCapacity >> 1);// 新容量仍然小于最小所需容量,则使用最小所需容量为新容量if (newCapacity - minCapacity < 0)newCapacity = minCapacity;// 新容量超过最大数组容量时,调用hugeCapacity(minCapacity);调整容量// MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8 if (newCapacity - MAX_ARRAY_SIZE > 0)newCapacity = hugeCapacity(minCapacity);// 将旧数组复制到新数组中,新数组容量为newCapacity,即原来的1.5倍elementData = Arrays.copyOf(elementData, newCapacity);
}private static int hugeCapacity(int minCapacity) {if (minCapacity < 0) // overflowthrow new OutOfMemoryError();// 最小所需容量大于MAX_ARRAY_SIZE,则使用Integer最大值,// 否则使用MAX_ARRAY_SIZE = MAX_ARRAY_SIZE - 8;return (minCapacity > MAX_ARRAY_SIZE) ?Integer.MAX_VALUE :MAX_ARRAY_SIZE;
}
ensureCapacity方法
在添加大量元素的时候先调用该方法进行扩容,减少扩容的次数(数组复制消耗性能)
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);}
}
indexOf方法
// 正向迭代数组判断有相同元素存在,有则返回数组下标,否则返回-1
public int indexOf(Object o) {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;
}
lastIndexOf方法
// 反向迭代数组判断有相同元素存在,有则返回数组下标,否则返回-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;
}
toArray方法
// 将列表中的数组按实际元素个数复制到新的Object数组中并返回
public Object[] toArray() {return Arrays.copyOf(elementData, size);
}
public static <T> T[] copyOf(T[] original, int newLength) {return (T[]) copyOf(original, newLength, original.getClass());
}
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {@SuppressWarnings("unchecked")T[] copy = ((Object)newType == (Object)Object[].class)? (T[]) new Object[newLength]: (T[]) Array.newInstance(newType.getComponentType(), newLength);System.arraycopy(original, 0, copy, 0,Math.min(original.length, newLength));return copy;
}