本文是針對Java 1.8的源代碼進行解析的,可能會和其餘版本有所出入。java
**繼承:**AbstractList數組
**實現:**List<E>, RandomAccess, Cloneable, Serializable接口緩存
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable{ }
private static final int DEFAULT_CAPACITY = 10;
private static final Object[] EMPTY_ELEMENTDATA = {};
// 無參構造函數建立的數組 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[] elementData;
private int size;
源碼解釋:多線程
public ArrayList(int initialCapacity) { // 若是初始化時ArrayList大小大於0 if (initialCapacity > 0) { // new一個該大小的object數組賦給elementData this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { // 若是大小爲0 // 將空數組賦給elementData this.elementData = EMPTY_ELEMENTDATA; } else { // 小於0 // 則拋出IllegalArgumentException異常 throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } }
源碼解釋:dom
public ArrayList() { // 直接將空數組賦給elementData this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }
源碼解釋:函數
參數c爲一個Collection,Collection的實現類大概有如下幾種經常使用類型:測試
這個構造方法的意思是,將一個Collection實現類的對象轉換爲一個ArrayList,可是c容器裝的內容ui
必須爲ArrayList裝的內容的子類。例如,將一個裝了String內容的HashSet轉換爲裝了String內容的this
ArrayList,使得ArrayList的大小和值數組都是HashSet的大小和值數組。具體實現以下代碼,首先調.net
用c(Collection的具體實現類)的toArray方法,具體你們能夠看各個實現類的toArray方法,可是大
概意思都是將c容器轉換爲object類型的數組,由於它們的返回值都是object[]。之於下面的兩個判斷
是當獲得的elementData的類名不是Object類名的時候或者是長度爲0的時候纔會執行。
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 { // replace with empty array. this.elementData = EMPTY_ELEMENTDATA; } }
**說明:**將ArrayList的容量設置爲當前size的大小。首先須要明確一個概念,ArrayList的size就是ArrayList的元素個數,length是ArrayList申請的內容空間長度。ArrayList每次都會預申請多一點空間,以便添加元素的時候不須要每次都進行擴容操做,例如咱們的元素個數是10個,它申請的內存空間一定會大於10,即length>size,而這個方法就是把ArrayList的內存空間設置爲size,去除沒有用到的null值空間。這也就是咱們爲何每次在獲取數據長度是都是調用list.size()而不是list.length()。
**源碼解釋:**首先modCount是從類 java.util.AbstractList 繼承的字段,這個字段主要是爲了防止在多線程操做的狀況下,List發生結構性的變化,什麼意思呢?就是防止一個線程正在迭代,另一個線程進行對List進行remove操做,這樣當咱們迭代到最後一個元素時,很明顯此時List的最後一個元素爲空,那麼這時modCount就會告訴迭代器,讓其拋出異常 ConcurrentModificationException。
若是沒有這一個變量,那麼系統確定會報異常ArrayIndexOutOfBoundsException,這樣的異常顯然不是應該出現的(這些運行時錯誤都是使用者的邏輯錯誤致使的,咱們的JDK那麼高端,不會出現使用錯誤,咱們只拋出使用者形成的錯誤,而這個錯誤是設計者應該考慮的),爲了不出現這樣的異常,定義了檢查。
(引用自:郭無意,詳情能夠看他在知乎的回答:https://www.zhihu.com/question/24086463/answer/64717159)。
public void trimToSize() { modCount++; // 若是size小於length if (size < elementData.length) { // 從新將elementData設置大小爲size elementData = (size == 0) ? EMPTY_ELEMENTDATA : Arrays.copyOf(elementData, size); } }
**說明:**返回ArrayList的大小
**源碼解釋:**直接返回size
public int size() { return size; }
**說明:**返回是否爲空
**源碼解釋: **直接返回判斷size==0
public boolean isEmpty() { return size == 0; }
**說明:**對象o在ArrayList中的下標位置,若是存在返回位置i,不存在返回-1
**源碼解釋:**遍歷ArrayList的大小,比較o和容器內的元素,若相等,則返回位置i,若遍歷完都不相等,返回-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; }
**說明:**是否包含對象o
**源碼解釋:**調用indexOf()方法獲得下標,存在則下標>=0,不存在爲-1,即只要比較下標和0的大小便可。
public boolean contains(Object o) { return indexOf(o) >= 0; }
**說明:**返回容器內出現o的最後一個位置
**源碼解釋:**從後向前遍歷,獲得第一個出現對象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; }
**說明:**返回此 ArrayList 實例的淺表副本。
源碼解釋:
public Object clone() { try { // 調用父類(翻看源碼可見是Object類)的clone方法獲得一個ArrayList副本 ArrayList<?> v = (ArrayList<?>) super.clone(); // 調用Arrays類的copyOf,將ArrayList的elementData數組賦值給副本的elementData數組 v.elementData = Arrays.copyOf(elementData, size); v.modCount = 0; // 返回副本v return v; } catch (CloneNotSupportedException e) { throw new InternalError(e); } }
**說明:**ArrayList 實例轉換爲。
**源碼解釋:**直接調用Arrays類的copyOf。
public Object[] toArray() { return Arrays.copyOf(elementData, size); }
**說明:**將ArrayList裏面的元素賦值到一個數組中去
**源碼解釋:**若是a的長度小於ArrayList的長度,直接調用Arrays類的copyOf,返回一個比a數組長度要大的新數組,裏面元素就是ArrayList裏面的元素;若是a的長度比ArrayList的長度大,那麼就調用System.arraycopy,將ArrayList的elementData數組賦值到a數組,而後把a數組的size位置賦值爲空。 public <T> T[] toArray(T[] a) { if (a.length < size) // Make a new array of a's runtime type, but my contents: return (T[]) Arrays.copyOf(elementData, size, a.getClass()); System.arraycopy(elementData, 0, a, 0, size); if (a.length > size) a[size] = null; return a; }
**說明:**測試index是否越界
源碼解釋:
private void rangeCheck(int index) { // 若是下標超過ArrayList的數組長度 if (index >= size) // 拋出IndexOutOfBoundsException異常 throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); }
**說明:**獲取index位置的元素
**源碼解釋:**先檢查是否越界,而後返回ArrayList的elementData數組index位置的元素。
public E get(int index) { // 檢查是否越界 rangeCheck(index); // 返回ArrayList的elementData數組index位置的元素 return elementData(index); }
**說明:**設置index位置的元素值了element,返回該位置的以前的值
源碼解釋:
public E set(int index, E element) { // 檢查是否越界 rangeCheck(index); // 調用elementData(index)獲取到當前位置的值 E oldValue = elementData(index); // 將element賦值到ArrayList的elementData數組的第index位置 elementData[index] = element; return oldValue; }
**說明:**獲得最小擴容量
源碼解釋:
private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { // 獲取默認的容量和傳入參數的較大值 minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); }
**說明:**判斷是否須要擴容
源碼解釋:
private void ensureExplicitCapacity(int minCapacity) { modCount++; // 若是最小須要空間比elementData的內存空間要大,則須要擴容 if (minCapacity - elementData.length > 0) grow(minCapacity); }
**說明:**幫助ArrayList動態擴容的核心方法
源碼解釋:
// MAX_VALUE爲231-1,MAX_ARRAY_SIZE 就是獲取Java中int的最大限制,以防止越界 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; private void grow(int minCapacity) { // 獲取到ArrayList中elementData數組的內存空間長度 int oldCapacity = elementData.length; // 擴容至原來的1.5倍 int newCapacity = oldCapacity + (oldCapacity >> 1); // 再判斷一下新數組的容量夠不夠,夠了就直接使用這個長度建立新數組, // 不夠就將數組長度設置爲須要的長度 if (newCapacity - minCapacity < 0) newCapacity = minCapacity; // 判斷有沒超過最大限制 if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // 調用Arrays.copyOf方法將elementData數組指向新的內存空間時newCapacity的連續空間 // 並將elementData的數據複製到新的內存空間 elementData = Arrays.copyOf(elementData, newCapacity); }
**說明:**添加元素e
源碼解釋:
public boolean add(E e) { // 擴容 ensureCapacityInternal(size + 1); // 將e賦值給elementData的size+1的位置。 elementData[size++] = e; return true; }
**說明:**在ArrayList的index位置,添加元素element
源碼解釋:
public void add(int index, E element) { // 判斷index是否越界 rangeCheckForAdd(index); // 擴容 ensureCapacityInternal(size + 1); // 將elementData從index位置開始,複製到elementData的index+1開始的連續空間 System.arraycopy(elementData, index, elementData, index + 1, size - index); // 在elementData的index位置賦值element elementData[index] = element; // ArrayList的大小加一 size++; }
**說明:**在ArrayList的移除index位置的元素
源碼解釋:
public E remove(int index) { // 判斷是否越界 rangeCheck(index); modCount++; // 讀取舊值 E oldValue = elementData(index); // 獲取index位置開始到最後一個位置的個數 int numMoved = size - index - 1; if (numMoved > 0) // 將elementData數組index+1位置開始拷貝到elementData從index開始的空間 System.arraycopy(elementData, index+1, elementData, index, numMoved); // 使size-1 ,設置elementData的size位置爲空,讓GC來清理內存空間 elementData[--size] = null; // clear to let GC do its work return oldValue; }
**說明:**在ArrayList的移除對象爲O的元素,跟indexOf方法思想基本一致
源碼解釋:
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; }
**說明:**設置所有元素爲null值,並設置size爲0。
**源碼解釋:**可見clear操做並非從空間內刪除,只是設置爲null值,等待垃圾回收機制來回收而已,把size設置爲0,以便咱們不會瀏覽到null值的內存空間。
public void clear() { modCount++; // clear to let GC do its work for (int i = 0; i < size; i++) elementData[i] = null; size = 0; }
**說明:**將Collection c的所有元素添加到ArrayList中
源碼解釋:
public boolean addAll(Collection<? extends E> c) { // 將c轉換爲數組a Object[] a = c.toArray(); // 獲取a佔的內存空間長度賦值給numNew int numNew = a.length; // 擴容至size + numNew ensureCapacityInternal(size + numNew); // Increments modCount // 將a的第0位開始拷貝至elementData的size位開始,拷貝長度爲numNew System.arraycopy(a, 0, elementData, size, numNew); // 將size增長numNew size += numNew; // 若是c爲空,返回false,c不爲空,返回true return numNew != 0; }
**說明:**從第index位開始,將c所有拷貝到ArrayList
源碼解釋:
public boolean addAll(int index, Collection<? extends E> c) { // 判斷index大於size或者是小於0,若是是,則拋出IndexOutOfBoundsException異常 rangeCheckForAdd(index); // 將c轉換爲數組a Object[] a = c.toArray(); int numNew = a.length; // 擴容至size + numNew ensureCapacityInternal(size + numNew); // Increments modCount // 獲取須要添加的個數 int numMoved = size - index; if (numMoved > 0) System.arraycopy(elementData, index, elementData, index + numNew, numMoved); System.arraycopy(a, 0, elementData, index, numNew); size += numNew; return numNew != 0; }
**說明:**根據complement值,將ArrayList中包含c中元素的元素刪除或者保留
源碼解釋:
private boolean batchRemove(Collection<?> c, boolean complement) { final Object[] elementData = this.elementData; // 定義一個w,一個r,兩個同時右移 int r = 0, w = 0; boolean modified = false; try { // r先右移 for (; r < size; r++) // 若是c中不包含elementData[r]這個元素 if (c.contains(elementData[r]) == complement) // 則直接將r位置的元素賦值給w位置的元素,w自增 elementData[w++] = elementData[r]; } finally { // 防止拋出異常致使上面r的右移過程沒完成 if (r != size) { // 將r未右移完成的位置的元素賦值給w右邊位置的元素 System.arraycopy(elementData, r, elementData, w, size - r); // 修改w值增長size-r w += size - r; } if (w != size) { // 若是有被覆蓋掉的元素,則將w後面的元素都賦值爲null for (int i = w; i < size; i++) elementData[i] = null; modCount += size - w; // 修改size爲w size = w; modified = true; } } return modified; }
**說明:**ArrayList移除c中的全部元素
源碼解釋:
public boolean removeAll(Collection<?> c) { // 若是c爲空,則拋出空指針異常 Objects.requireNonNull(c); // 調用batchRemove移除c中的元素 return batchRemove(c, false); }
**說明:**和removeAll相反,僅保留c中全部的元素
源碼解釋:
public boolean retainAll(Collection<?> c) { Objects.requireNonNull(c); // 調用batchRemove保留c中的元素 return batchRemove(c, true); }
**說明:**返回一個Iterator對象,Itr爲ArrayList的一個內部類,其實現了Iterator<E>接口
public Iterator<E> iterator() { return new Itr(); }
**說明:**返回一個ListIterator對象,ListItr爲ArrayList的一個內部類,其實現了ListIterator<E> 接口
源碼解釋:
public ListIterator<E> listIterator() { return new ListItr(0); }
說明:返回一個從index開始的ListIterator對象
源碼解釋:
public ListIterator<E> listIterator(int index) { if (index < 0 || index > size) throw new IndexOutOfBoundsException("Index: "+index); return new ListItr(index); }
**說明:**根據兩個參數,獲取到一個子序列
源碼解釋:
public List<E> subList(int fromIndex, int toIndex) { // 檢查異常 subListRangeCheck(fromIndex, toIndex, size); // 調用SubList類的構造方法 return new SubList(this, 0, fromIndex, toIndex); }
(1)private class Itr implements Iterator<E> (2)private class ListItr extends Itr implements ListIterator<E> (3)private class SubList extends AbstractList<E> implements RandomAccess (4)static final class ArrayListSpliterator<E> implements Spliterator<E>
ArrayList有四個內部類,
其中的Itr是實現了Iterator接口,同時重寫了裏面的hasNext(),next(),remove()等方法;
其中的ListItr繼承Itr,實現了ListIterator接口,同時重寫了hasPrevious(),nextIndex(), previousIndex(),previous(),set(E e),add(E e)等方法,因此這也能夠看出了Iterator和ListIterator的區別,就是ListIterator在Iterator的基礎上增長了添加對象,修改對象,逆向遍歷等方法,這些是Iterator不能實現的。具體能夠參考http://blog.csdn.net/a597926661/article/details/7679765。
其中的SubList繼承AbstractList,實現了RandmAccess接口,類內部實現了對子序列的增刪改查等方法,但它同時也充分利用了內部類的優勢,就是共享ArrayList的全局變量,例如檢查器變量modCount,數組elementData等,因此SubList進行的增刪改查操做都是對ArrayList的數組進行的,並無建立新的數組。
最後一個比較我的比較少接觸,你們須要自行度娘。
筆者技術真的是通常般,寫這個爲了加深理解的同時給懼怕看源代碼的朋友一點鼓勵,因此筆者在寫的過程當中有查閱不少資料來努力減小錯誤,可是若有錯漏之處,但願大神們指出,我會第一時間修改,以避免誤人子弟,也但願和筆者同樣基礎不夠好的朋友不要畏懼看源碼,源碼看起來並不會很難,並且多看源代碼會對Java更深入的理解。