public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
ArrayList繼承AbstractList,也實現了List和RandomAccess(一個空接口,也就是標記接口。),Cloneable(可被克隆), Serializable接口。java
//默認容量 private static final int DEFAULT_CAPACITY = 10; //空對象數組(initialCapacity == 0時返回) private static final Object[] EMPTY_ELEMENTDATA = {}; //調用無參構造方法,返回的是該數組 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //元素數組,保存添加到ArrayList中的元素 transient Object[] elementData; //ArrayList大小 private int size;
elementData是transient修飾,因此elementData不能被序列化。可是ArrayList又是能夠被序列化的,這是爲什麼?數組
private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException{ // Write out element count, and any hidden stuff int expectedModCount = modCount; s.defaultWriteObject(); // Write out size as capacity for behavioural compatibility with clone() s.writeInt(size); // Write out all elements in the proper order. for (int i=0; i<size; i++) { s.writeObject(elementData[i]); } if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } }
private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { elementData = EMPTY_ELEMENTDATA; // Read in size, and any hidden stuff s.defaultReadObject(); // Read in capacity s.readInt(); // ignored if (size > 0) { // be like clone(), allocate array based upon size not capacity ensureCapacityInternal(size); Object[] a = elementData; // Read in all elements in the proper order. for (int i=0; i<size; i++) { a[i] = s.readObject(); } } }
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() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }
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; } }
public boolean add(E e) { //確保elementData數組的大小 ensureCapacityInternal(size + 1); //在結尾處添加元素 elementData[size++] = e; return true; }
上面是add(E e)方法的源碼,在添加元素前會調用 ensureCapacityInternal(size + 1);確保elementData數組的大小。dom
private void ensureCapacityInternal(int minCapacity) { // 判斷元素數組是否爲空數組 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //minCapacity最少=DEFAULT_CAPACITY=10 minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); }
private void ensureExplicitCapacity(int minCapacity) { // List結構性修改加1 modCount++; //minCapacity大於elementData數組長度 if (minCapacity - elementData.length > 0) //增加 grow(minCapacity); }
private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; //oldCapacity >> 1右移一位,這裏至關於擴容1.5倍 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); }
上面的擴容方法中 oldCapacity >> 1 代表elementData.length右移一位,擴容後的容量爲原始容量的1.5倍函數
public E remove(int index) { rangeCheck(index); modCount++; E oldValue = elementData(index); //須要移動的元素個數 int numMoved = size - index - 1; //刪除的不是最後一個元素 if (numMoved > 0) //index後的元素都向前移動一位 System.arraycopy(elementData, index+1, elementData, index, numMoved); //size減一,釋放引用,方便垃圾回收器進行垃圾回收 elementData[--size] = null; // clear to let GC do its work return oldValue; }
remove(int index)方法會先計算須要移動的元素個數,index後的元素都向前移動一位(調用System.arraycopy方法移動),而後size減一,賦值爲null釋放引用,方便垃圾回收器進行垃圾回收。性能
例如要刪除集合中的「a」this
Iterator<String> iterator = list.iterator(); while (iterator.hasNext()){ if ("a".equals(iterator.next())) { iterator.remove(); } }
或者使用lambda表達式線程
list.removeIf("x"::equals);
public E set(int index, E element) { //檢查索引 rangeCheck(index); E oldValue = elementData(index); elementData[index] = element; //返回舊值 return oldValue; }
public E get(int index) { rangeCheck(index); return elementData(index); }
public void trimToSize() { modCount++; if (size < elementData.length) { elementData = (size == 0) ? EMPTY_ELEMENTDATA : Arrays.copyOf(elementData, size); } }