构造函数
ArrayList 有三个构造函数,默认不带参数的构造函数就是初始化一个空数组。
//一个空数组private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};//实际存储元素的数组transient Object[] elementData;public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}
带一个 int 类型的容量参数的构造函数,可以指定 ArrayList 的容量大小。
//空数组private static final Object[] EMPTY_ELEMENTDATA = {};public ArrayList(int initialCapacity) {if (initialCapacity > 0) {//容量大于 0 就构建一个 Object 的数组this.elementData = new Object[initialCapacity];} else if (initialCapacity == 0) {//容量等于 0 就是一个空数组this.elementData = EMPTY_ELEMENTDATA;} else {//容量小于 0 抛出异常throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);}}
带一个集合的构造函数, 将集合转换成 Object[] 类型后拷贝到 elementData 中。
public ArrayList(Collection<? extends E> c) {//集合转为数组Object[] a = c.toArray();if ((size = a.length) != 0) {//集合是不是 ArrayList 类型if (c.getClass() == ArrayList.class) {elementData = a;} else {//将集合元素拷贝成 Object[] 到 elementDataelementData = Arrays.copyOf(a, size, Object[].class);}} else {//空元素elementData = EMPTY_ELEMENTDATA;}}
常用函数
add()
先从 ArrayList 最常用的方法 add() 开始讲起,add() 方法就是将元素添加到 elementData 的末尾。平均时间复杂度为 O(1)。
//ArrayList.add()public boolean add(E e) {//检查数组是否存放的下ensureCapacityInternal(size + 1);//添加到末尾elementData[size++] = e;return true;}//ArrayList.ensureCapacityInternal()private void ensureCapacityInternal(int minCapacity) {ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));}//ArrayList.calculateCapacity()private static int calculateCapacity(Object[] elementData, int minCapacity) {//检查时不是默认时的空数组,是默认时的空数组,初始化的容量就是 10if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {return Math.max(DEFAULT_CAPACITY, minCapacity);}return minCapacity;}//ArrayList.ensureExplicitCapacity()private void ensureExplicitCapacity(int minCapacity) {modCount++;if (minCapacity - elementData.length > 0)grow(minCapacity);}//最大容量private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;//ArrayList.grow()private void grow(int minCapacity) {int oldCapacity = elementData.length;//新长度时原来长度的 1.5 倍int newCapacity = oldCapacity + (oldCapacity >> 1);//新长度小于实际容量,就用实际容量if (newCapacity - minCapacity < 0)newCapacity = minCapacity;//新长度太大了,就用最大的容量if (newCapacity - MAX_ARRAY_SIZE > 0)newCapacity = hugeCapacity(minCapacity);//copy 成一个新数组elementData = Arrays.copyOf(elementData, newCapacity);}
- 扩容的大小为原长度+1/2的原长度
- 如果扩容长度比传入的最小容量小,则使用最小容量,如果扩容长度超过设定的最大容量,则实际用最大容量
-
add(int index, E element)将元素插入到指定的位置,主要的操作是将指定位置之后的元素往后移动一个位置,空出 index 位置。平均时间复杂度为 O(n)。
//ArrayList.add(int index, E element)public void add(int index, E element) {//index的越界检查rangeCheckForAdd(index);//扩容ensureCapacityInternal(size + 1);//将 index 之后的所有元素 copy 到往后挪动一位System.arraycopy(elementData, index, elementData, index + 1,size - index);//将 index 位置放入新元素elementData[index] = element;//数量 + 1size++;}
get()get()应该是第二个常用的函数,可以返回随机位置的元素。需要注意的是越界时,超过容量返回的是IndexOutOfBoundsException异常,index 太小返回的是ArrayIndexOutOfBoundsException异常。平均时间复杂度为 O(1)。 ```java //ArrayList.get() public E get(int index) { //index 越界检查 rangeCheck(index); //返回指定位置的元素 return elementData(index); }
//ArrayList.rangeCheck() private void rangeCheck(int index) { if (index >= size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } //ArrayList.elementData() E elementData(int index) { return (E) elementData[index]; }
<a name="HLAUU"></a>#### `remove()`删除指定位置的元素,并返回删除的元素。平均时间复杂度为 O(n)。```java//ArrayList.remove()public E remove(int index) {//越界检查rangeCheck(index);modCount++;//取出元素E oldValue = elementData(index);//拷贝数组,将 index 之后的元素往前移动一个位置int numMoved = size - index - 1;if (numMoved > 0)System.arraycopy(elementData, index+1, elementData, index,numMoved);//最后一个元素置 nullelementData[--size] = null;return oldValue;}
remove(Object o)
删除指定的元素,需要循环数组删除第一个指定的元素。平均时间复杂度为 O(n)。
//ArrayList.remove(Object o)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;}//ArrayList.fastRemoveprivate void fastRemove(int index) {modCount++;int numMoved = size - index - 1;if (numMoved > 0)System.arraycopy(elementData, index+1, elementData, index,numMoved);elementData[--size] = null;}
总结

- ArrayList 内部用一个数组存储元素,容量不够时会扩容原来的一半。
- ArrayList 实现了
RandomAccess,支持随机访问。 - ArrayList 实现了
Cloneable,支持被拷贝克隆。 - ArrayList 删除指定元素和指定位置上的元素的效率不高,需要遍历数组。
