1 ArrayList 中的基本方法实现
ArrayList 方法签名
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
RandomAccess接口说明ArrayList可随机访问的。继承自AbstractList
ArrayList中的实例域:
private static final int DEFAULT_CAPACITY = 10;
transient Object[] elementData; // non-private to simplify nested class access
private int size;
elementData 数组用于保存数据
DEFAULT_CAPACITY 没有指定数组长度时的默认数组容量
size表示数组中真正包含的元素,size<=capacity
随机读取的实现 get
public E get(int index) {
// 数组范围检查
rangeCheck(index);
//实际上就是对数组elementData[index]的访问
return elementData(index);
}
//范围检查,并没有对index < 0 进行检查。用的是数组访问的负数越界异常java.lang.ArrayIndexOutOfBoundsException
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
@SuppressWarnings("unchecked")
E elementData(int index) {
return (E) elementData[index];
}
get() 首先checkRange, 此时没有对index是负数的检查。访问数组index<0,会抛出ArrayIndexOutOfBoundsException的错误。范围检查之后,直接elementDate[index]返回元素
get(index)的时间复杂度为 O(1), 这是ArrayList的优势
add
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
// DEFAULTCAPACITY_EMPTY_ELEMENTDATA空数组缓存,实例化空数组时无需每次都new一个数组,第一次添加时new一个新的数组。用于提升性能。
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
//当需要的最小的容量比数组的length大时,进行扩容
grow(minCapacity);
}
add(E e),首先需要进行容量检查 & modCount + 1,如果是DEFAULTCAPACITY_EMPTY_ELEMENTDATA需要分配新的数组。如果添加后的size超过当前的容量,需要扩容。添加则是 elementData[size++] = e;
public void add(int index, E element) {
// 范围检查
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1); // Increments modCount!!
//在某个位置上插入需要数组的copy,此时会有性能消耗
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
//rangeCheck
private void rangeCheckForAdd(int index) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
add(int index, E element):checkRange, copyOf array, add。该添加方法性能消耗在copy array上。
add的最好的情况(在数组末尾添加)时间复杂度为O(1), 最坏的情况下(在数组首添加)时间复杂度为O(n)。
扩容
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);
}
grow(),新的数组的长度是原来的1.5倍。再用Arrays.copyOf将旧的数组复制到新的数组中。
remove
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) {
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;
}
/*
* Private remove method that skips bounds checking and does not
* return the value removed.
*/
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
}
用index remove,先进行rangeCheck, 然后通过将index+1及后面的元素复制到index位置上,index就被删除了。
用object remove, 使用fastRemove。fastRemove是没有rangeCheck, 也不放回删除的元素的删除方法,也是通过数组的copy实现Index位置上元素的覆盖。
remove方法中都需要数组复制,所以性能上有消耗。
2 ArrayList 的迭代器
public Iterator<E> iterator() {
return new Itr();
}
ArrayList中返回的迭代器是Itr的实例。Itr是ArrayList的内部类,继承自Iterator,实现了基本的迭代器方法
private class Itr implements Iterator<E> {}
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;
public boolean hasNext() {
//下一个元素的索引 != size,表示还有下一个元素
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
//确认迭代器操作过程中没有对list上有structural modification
checkForComodification();
//当前要操作的index
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
//返回当前index上的元素
return (E) elementData[lastRet = i];
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
//调用的是ArrayList上的remove操作
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
// 在通过迭代器操作的过程中又对列表有结构上的更改,抛出异常
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
ArrayList中还有一个ListIterator。
public ListIterator<E> listIterator() {
return new ListItr(0);
}
ListItr是ArrayList的内部迭代器实现。ListIterator是一个双向的迭代器,有previous(),next()等操作
/**
* An optimized version of AbstractList.ListItr
*/
private class ListItr extends Itr implements ListIterator<E> {
ListItr(int index) {
super();
cursor = index;
}
public boolean hasPrevious() {
return cursor != 0;
}
public int nextIndex() {
return cursor;
}
public int previousIndex() {
return cursor - 1;
}
@SuppressWarnings("unchecked")
public E previous() {
checkForComodification();
int i = cursor - 1;
if (i < 0)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i;
return (E) elementData[lastRet = i];
}
public void set(E e) {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.set(lastRet, e);
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
public void add(E e) {
checkForComodification();
try {
int i = cursor;
ArrayList.this.add(i, e);
cursor = i + 1;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
}
ListItr继承自Itr。除了向后访问的方法之外。还添加了向前访问,以及add,set操作。
3. sublist
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size);
return new SubList(this, 0, fromIndex, toIndex);
}
ArrayList.sublist 操作实际上返回的是SubList实例。SubList是ArrayList的内部类,实际上生成的sublist指向的List还是原来的列表。也就是说,对于sublist的操作都会反应在原来的List对象上,并不会生成一个新的sub list。
public E set(int index, E e) {
rangeCheck(index);
checkForComodification();
E oldValue = ArrayList.this.elementData(offset + index);
//实际上都是对于ArrayList的elementData上的操作
ArrayList.this.elementData[offset + index] = e;
return oldValue;
}
public E get(int index) {
rangeCheck(index);
checkForComodification();
//实际上都是对于ArrayList的elementData上的操作
return ArrayList.this.elementData(offset + index);
}
4. ArrayList 总结
ArrayList 是列表的数组实现,可随机访问(通过数组的直接寻址)。
ArrayList 访问效率高,但是对于添加和删除的效率低。所以不利于有大量添加和删除业务的容器。此时需要用LinkedList作为容器。
ArrayList中有双向访问的迭代器(ListIterator)实现,可以双向访问,并且可以在迭代器访问时添加和删除。
ArrayList中的子列表本质上指向的是原来的列表,所以对于子列表的操作会反应到原来的列表中。
4. ArrayList & Vector
- ArrayList 的方法都不是同步的,所以在多线程中对同一个ArrayList操作需要额外的同步工作。Vector中已经做了同步,无需再有额外的同步机制
- ArrayList 的扩容是原来的1.5倍,添加了50%的空间。Vector 通过capacityIncrement开控制容量的增长量的,默认情况下是增加100%的。