public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable{}
說明:java
//數組默認大小10 private static final int DEFAULT_CAPACITY = 10; //默認數據 空數組 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[] elementData;
這裏用transient
修飾,是爲了防止自動序列化。緣由:數組
因爲 ArrayList 是基於動態數組實現的,因此並非全部的空間都被使用。所以使用了 transient 修飾,能夠防止被自動序列化。
因此,ArrayList也自定義了序列化和反序列化方法,只序列化當前存放的數據安全
private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException{ int expectedModCount = modCount; s.defaultWriteObject(); s.writeInt(size); // 這裏只序列化已經有的數據,並非全部空間都序列化 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; s.defaultReadObject(); s.readInt(); if (size > 0) { int capacity = calculateCapacity(elementData, size); SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, capacity); ensureCapacityInternal(size); Object[] a = elementData; // 反序列化,讀取數據 for (int i=0; i<size; i++) { a[i] = s.readObject(); } } }
private int size;//ArrayList的數組大小
//修改次數 父類AbstractList全部 protected transient int modCount = 0; //指望修改次數 父類AbstractList的內部類Itr全部 int expectedModCount = modCount;
說明多線程
ArrayList的全部關於結構變化的操做(add、remove、addAll、removeRange和clear),都會讓modCount++ 而在私有內部類迭代器Itr中定義了變量expectedModCount和checkForComodification方法 private class Itr implements Iterator<E> { //指望的修改次數 int expectedModCount = modCount; //修改檢查方法() final void checkForComodification() { //若是修改數和指望修改數不一致,拋出異常 if (modCount != expectedModCount) throw new ConcurrentModificationException(); } }
好處:快速失敗dom
若是在多線程環境中,使用迭代器操做ArrayList的時候可能形成修改次數不一致,每次迭代器更新數據前檢查,來保證數據安全和一致,若是不一致能讓迭代快速失敗
public boolean add(E e) { ensureCapacityInternal(size + 1); // 擴容(若是必要),而且 modCount++ elementData[size++] = e;//數組尾部添加元素 return true; }
//在指定位置添加元素 public void add(int index, E element) { rangeCheckForAdd(index);//校驗index是否大於數組長度或者小於0 ensureCapacityInternal(size + 1); // 擴容(若是必要),而且 modCount++ //對數據進行復制,目的是把 index 位置空出來放本次插入的數據,並將後面的數據向後移動一個位置 System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element;//將插入的值放到指定位置index size++;//將 size + 1 }
public boolean addAll(Collection<? extends E> c) { Object[] a = c.toArray(); int numNew = a.length; ensureCapacityInternal(size + numNew); //數組複製和移動 System.arraycopy(a, 0, elementData, size, numNew); size += numNew; return numNew != 0; }
在指定位置設置新的值,並返回舊值this
public E set(int index, E element) { rangeCheck(index);//檢查index是否超過數組大小 E oldValue = elementData(index);//獲取到以前的值 elementData[index] = element;//設置新值 return oldValue;//返回以前的值 }
//擴容檢測 private void ensureCapacityInternal(int minCapacity) { ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); } // private void ensureExplicitCapacity(int minCapacity) { modCount++; // 當數組容量不足,調用grow進行擴容 if (minCapacity - elementData.length > 0) grow(minCapacity); } //擴容 private void grow(int minCapacity) { int oldCapacity = elementData.length;//獲取當前容量大小 int newCapacity = oldCapacity + (oldCapacity >> 1);//新容量=當前容量的1.5倍 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); }
public E get(int index) { rangeCheck(index);//檢查index是否超過數組大小 return elementData(index);//返回數組指定位置的元素 }
移除指定位置元素,返回被移除位置上的元素值線程
public E remove(int index) { rangeCheck(index);//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; //清除數組,讓gc收集 return oldValue; }
public boolean remove(Object o) { if (o == null) {//移除null值 for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); return true; } } else {//移除非null值 for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); return true; } } return false; } //快速移除,數組複製和移動 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 }
線程安全code
Vector相似於ArrayList,是一個動態數組,只是它是一個線程安全的數組容器。它的add、set、remove方法都是用synchronized來修飾的。
擴容對象
//Vector的擴容,不是按1.5倍,二是1倍 private void grow(int minCapacity) { int oldCapacity = elementData.length; //按原來的1倍擴容 int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); elementData = Arrays.copyOf(elementData, newCapacity); }