ArrayList是基于数组实现的List,数组的容量可以改变。ArrayList中允许存放null元素。
ArrayList是unsynchronized的,而Vector是synchronized的。这是两者的主要区别,除此之外两者大致相似。
在ArrayList中,size(), get(),isEmpty(), set(),iterator(), 和listIterator()等方法的时间复杂度都是常数级别的。add操作需要的时间平均下来也是常数级别,也就是说,添加n个元素的时间复杂度为O(n)。所有其他操作基本上都以线性时间运行。 与LinkedList的实现相比,ArrayList的常数因子较低。
同样的,ArrayList的iterator具有fail-fast机制。
下面看源码:
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
由声明可以看出,ArrayList继承自AbstractList,实现了List等接口。
//默认初始容量为10
private static final int DEFAULT_CAPACITY = 10;
/**
* 所有新建的空的实例对象共享的一个空的数组实例
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
* 所有新建的具有默认size的空的实例对象共享的一个空的数组实例
* 与EMPTY_ELEMENTDATA的区别在于,使用DEFAULTCAPACITY_EMPTY_ELEMENTDATA可以知道当
* 添加第一个元素时,数组容量应该扩大为多少
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
用于存储元素的数组elementData,数组的长度就是ArrayList的容量。任何一个空的ArrayList,如果它的elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA,那么,在添加第一个元素时,它的容量会被扩充为默认容量:
transient Object[] elementData; // non-private to simplify nested class access
存放的元素的数量为size:
//The size of the ArrayList ().
private int size;
ArrayList具有的构造函数如下:
根据制定的初始容量新建一个ArrayList,如果制定容量大于0,则新建一个数组,若容量指定为0,直接另elementData=EMPTY_ELEMENTDATA,若小于0就会抛出异常。
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);
}
}
默认的构造函数如下,将elementData指向空的数组DEFAULTCAPACITY_EMPTY_ELEMENTDATA,但是,当添加第一个元素时,容量将被扩容为默认初始容量(10)。
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
还可以根据另外一个容器来初始化一个ArrayList,将指定容器中的元素按照其iterator迭代的顺序取出来并依次添加到ArrayList中:
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;
}
}
方法trimToSize的作用是,将ArrayList的容量(即数组的长度)设置为List中已经存放的元素的数量(size)。通过此操作,可以将ArrayList的存储空间最小化。
public void trimToSize() {
modCount++;
if (size < elementData.length) {
elementData = (size == 0)
? EMPTY_ELEMENTDATA
: Arrays.copyOf(elementData, size);
}
}
方法ensureCapacity的作用是在必要的情况下增加ArrayList的容量以确保ArrayList中能够容纳至少minCapacitiy的元素。
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);
}
}
size()、isEmpty()和contains()方法的实现:
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
indexOf()方法:在数组存放的元素中从前到后查找元素o第一次出现时的下标(允许重复元素),如果元素不存在,返回-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()方法:在数组存放的元素中从后往前查找元素o第一次出现时的下标(允许重复元素),如果元素不存在,返回-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;
}
get()方法的实现:
@SuppressWarnings("unchecked")
E elementData(int index) {
return (E) elementData[index];
}
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
set()方法:替换相应位置上的元素
public E set(int index, E element) {
rangeCheck(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
add()方法添加元素:
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!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
删除指定位置上的元素,其后的元素全都左移一个位置:
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;
}
删除指定元素o在ArrayList中从前往后出现的第一个,如果ArrayList中没有存放该元素,则不做任何其他操作。如果存在且删除了,返回true;如果不存在该元素,返回false。
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;
}
移除List中所有的元素:
public void clear() {
modCount++;
// clear to let GC do its work
for (int i = 0; i < size; i++)
elementData[i] = null;
size = 0;
}
迭代器iterator:
public Iterator<E> iterator() {
return new Itr();
}
/**
* An optimized version of AbstractList.Itr
*/
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
Itr() {}
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
@Override
@SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> consumer) {
Objects.requireNonNull(consumer);
final int size = ArrayList.this.size;
int i = cursor;
if (i >= size) {
return;
}
final Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length) {
throw new ConcurrentModificationException();
}
while (i != size && modCount == expectedModCount) {
consumer.accept((E) elementData[i++]);
}
// update once at end of iteration to reduce heap write traffic
cursor = i;
lastRet = i - 1;
checkForComodification();
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}