ArrayList是一個非線程安全的有序集合, 按照添加順序排列, 能夠隨機添加或刪除元素, 支持任意類型元素, 支持泛型。java
對於ArrayList, JDK1.8相對於JDK1.9沒有什麼大變化, JDK1.8版本比JDK1.7版增長了一些函數編程特性方法, 以下編程
//循環每一個元素, 以元素爲參數執行action操做 @Override public void forEach(Consumer<? super E> action) { ... } //經過Predicate(斷言函數接口)實現過濾刪除 @Override public boolean removeIf(Predicate<? super E> filter) { Objects.requireNonNull(filter); .... return anyToRemove; } //經過UnaryOperator(一元操做函數接口)來實現替換 @Override @SuppressWarnings("unchecked") public void replaceAll(UnaryOperator<E> operator) { ... }
/** * The array buffer into which the elements of the ArrayList are stored. * The capacity of the ArrayList is the length of this array buffer. Any * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA * will be expanded to DEFAULT_CAPACITY when the first element is added. */ transient Object[] elementData; // non-private to simplify nested class access
從以上源碼能夠看出:數組
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); } } /** * Constructs an empty list with an initial capacity of ten. */ public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } 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; } }
ArrayList實例化有如下三種:安全
private void grow(int minCapacity) { //舊容量 int oldCapacity = elementData.length; //計算新容量 int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; //判斷是否超過數組容量上限 if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // 複製一個新容量的數組 elementData = Arrays.copyOf(elementData, newCapacity); } //設置爲大容量 private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; }
擴容經過grow()方法實現, 主要作了如下三項工做:數據結構
/** * 添加一個元素, 支持任何類型 * */ public boolean add(E e) { //確保內部容量能夠支持添加的元素 ensureCapacityInternal(size + 1); //向數組中添加元素 elementData[size++] = e; return true; } /** * 將元素添加到特定的索引位置 * * @param index 待添加元素的索引 * @param element 待添加元素 * @throws IndexOutOfBoundsException {@inheritDoc} */ public void add(int index, E element) { //檢查index是否超出數組的index限制,若是超過, //則拋出數組越界異常(IndexOutOfBoundsException) rangeCheckForAdd(index); //確保內部容量能夠支持添加的元素 ensureCapacityInternal(size + 1); //複製一個新數組, 目的是爲了移位,將插入點index以後的元素日後移動 System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; } //確保內部容量能夠支持添加的元素 private void ensureCapacityInternal(int minCapacity) { //若是數組爲空, 多是單元素添加或批量元素添加觸發當前操做 //單元素添加: minCapacity = DEFAULT_CAPACITY(至關於初始化默認容量) //批量元素添加: minCapacity不變 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } //確保準確的容量 ensureExplicitCapacity(minCapacity); } //確保準確的容量 private void ensureExplicitCapacity(int minCapacity) { //解決併發問題的,後續會提到 modCount++; // elementData新增元素後, 若是當前容量不能知足elementData的長度, 則進行擴容 if (minCapacity - elementData.length > 0) grow(minCapacity); }
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) { //查找爲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; } /* * 快速刪除, 不校驗index溢出, 不返還刪除元素對象 */ 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 }
/** * Returns the element at the specified position in this list. * * @param index index of the element to return * @return the element at the specified position in this list * @throws IndexOutOfBoundsException {@inheritDoc} */ public E get(int index) { rangeCheck(index); return elementData(index); }
ArrayList的 add, remove,get操做都沒有加鎖, 因此是非線程安全的。併發
protected transient int modCount = 0; 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; }
這個變量充斥着整個ArrayList類中, 凡有修改的地方就有他它, 它記錄着ArrayList元素修改次數。ide
下面來講明它的用處:函數
//迭代器 public ListIterator<E> listIterator(final int index) { //檢查修改狀態(modCount) checkForComodification(); rangeCheckForAdd(index); final int offset = this.offset; return new ListIterator<E>() { @SuppressWarnings("unchecked") public E next() { checkForComodification(); ...... } public void remove() { if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { ...... } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } public void add(E e) { checkForComodification(); try { ...... } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } } final void checkForComodification() { //若是不相等, 說明其餘線程修改了ArrayList元素 if (expectedModCount != ArrayList.this.modCount) throw new ConcurrentModificationException(); } ...... }; }
能夠看出在ListIterator迭代器中, 進行任何操做都會調用checkForComodification() 檢查modCount是否有變更, 若是有變更, 就表明其餘線程修改了ArrayList的元素,而後拋出ConcurrentModificationException異常.性能
它的做用是用於實現快速失敗機制(fail-fast), 當咱們對ArrayList的元素迭代時, 若是其它線程修改了某個元素, 會產生迭代結果會不正確或迭代失敗, 快速失敗機制能夠提早檢測迭代失敗問題, 避免浪費時間, 影響性能。ui