寫在前面
本文是針對Java 1.8的源代碼進行解析的,可能會和其他版本有所出入。
轉載自http://blog.csdn.net/ljcitworld/article/details/52041836
全局變量
1. 默認容量
-
private static final int DEFAULT_CAPACITY = 10;
2. 空的對象數組
-
private static final Object[] EMPTY_ELEMENTDATA = {};
3.默認的空數組
-
-
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
4.存放數據的數組的緩存變量,不可序列化
-
transient Object[] elementData;
5.數組的大小
構造方法
1.帶有容量initialCapacity的構造方法
源碼解釋:
-
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);
-
}
-
}
2.不帶參數的構造方法
源碼解釋:
-
public ArrayList() {
-
-
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
-
}
3.帶參數Collection的構造方法
源碼解釋:
參數c爲一個Collection,Collection的實現類大概有以下幾種常用類型:
- List:元素可以重複的容器
- Set: 元素不可重複的容器
- Queue:結構是一個隊列,先進先出
這個構造方法的意思是,將一個Collection實現類的對象轉換爲一個ArrayList,但是c容器裝的內容必須爲ArrayList裝的內容的子類。例如,將一個裝了String內容的HashSet轉換爲裝了String內容的ArrayList,使得ArrayList的大小和值數組都是HashSet的大小和值數組。具體實現如下代碼,首先調用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 {
-
-
this.elementData = EMPTY_ELEMENTDATA;
-
}
-
}
方法
1.trimToSize()
說明:將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++;
-
-
if (size < elementData.length) {
-
-
elementData = (size == 0)
-
? EMPTY_ELEMENTDATA
-
: Arrays.copyOf(elementData, size);
-
}
-
}
2.size()
說明:返回ArrayList的大小
源碼解釋:直接返回size
-
public int size() {
-
return size;
-
}
3.isEmpty()
說明:返回是否爲空
源碼解釋: 直接返回判斷size==0
-
public boolean isEmpty() {
-
return size == 0;
-
}
4.indexOf(Object o)
說明:對象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;
-
}
5.contains(Object o)
說明:是否包含對象o
源碼解釋:調用indexOf()方法得到下標,存在則下標>=0,不存在爲-1,即只要比較下標和0的大小即可。
-
public boolean contains(Object o) {
-
return indexOf(o) >= 0;
-
}
6.lastIndexOf(Object o)
說明:返回容器內出現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;
-
}
7.clone()
說明:返回此 ArrayList 實例的淺表副本。
源碼解釋:
-
public Object clone() {
-
try {
-
-
ArrayList<?> v = (ArrayList<?>) super.clone();
-
-
v.elementData = Arrays.copyOf(elementData, size);
-
v.modCount = 0;
-
-
return v;
-
} catch (CloneNotSupportedException e) {
-
throw new InternalError(e);
-
}
-
}
8.toArray()
說明:ArrayList 實例轉換爲。
源碼解釋:直接調用Arrays類的copyOf。
-
public Object[] toArray() {
-
return Arrays.copyOf(elementData, size);
-
}
9.toArray(T[] a)
說明:將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)
-
-
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
-
System.arraycopy(elementData, 0, a, 0, size);
-
if (a.length > size)
-
a[size] = null;
-
return a;
-
}
10.rangeCheck(int index)
說明:測試index是否越界
源碼解釋:
-
private void rangeCheck(int index) {
-
-
if (index >= size)
-
-
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
-
}
11.get(int index)
說明:獲取index位置的元素
源碼解釋:先檢查是否越界,然後返回ArrayList的elementData數組index位置的元素。
-
public E get(int index) {
-
-
rangeCheck(index);
-
-
return elementData(index);
-
}
12.set(int index, E element)
說明:設置index位置的元素值了element,返回該位置的之前的值
源碼解釋:
-
public E set(int index, E element) {
-
-
rangeCheck(index);
-
-
E oldValue = elementData(index);
-
-
elementData[index] = element;
-
return oldValue;
-
}
13.ensureCapacityInternal(int minCapacity)
說明:得到最小擴容量
源碼解釋:
-
private void ensureCapacityInternal(int minCapacity) {
-
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
-
-
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
-
}
-
ensureExplicitCapacity(minCapacity);
-
}
14.ensureExplicitCapacity(int minCapacity)
說明:判斷是否需要擴容
源碼解釋:
-
private void ensureExplicitCapacity(int minCapacity) {
-
modCount++;
-
-
if (minCapacity - elementData.length > 0)
-
grow(minCapacity);
-
}
15.grow()方法
說明:幫助ArrayList動態擴容的核心方法
源碼解釋:
-
-
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
-
-
-
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);
-
}
16.add(E e)
說明:添加元素e
源碼解釋:
-
public boolean add(E e) {
-
-
ensureCapacityInternal(size + 1);
-
-
elementData[size++] = e;
-
return true;
-
}
17.add(int index, E element)
說明:在ArrayList的index位置,添加元素element
源碼解釋:
-
public void add(int index, E element) {
-
-
rangeCheckForAdd(index);
-
-
ensureCapacityInternal(size + 1);
-
-
System.arraycopy(elementData, index, elementData, index + 1,
-
size - index);
-
-
elementData[index] = element;
-
-
size++;
-
}
18.remove(int index)
說明:在ArrayList的移除index位置的元素
源碼解釋:
-
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;
-
return oldValue;
-
}
19.remove(Object o)
說明:在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;
-
}
20.clear()
說明:設置全部元素爲null值,並設置size爲0。
源碼解釋:可見clear操作並不是從空間內刪除,只是設置爲null值,等待垃圾回收機制來回收而已,把size設置爲0,以便我們不會瀏覽到null值的內存空間。
-
public void clear() {
-
modCount++;
-
-
for (int i = 0; i < size; i++)
-
elementData[i] = null;
-
size = 0;
-
}
21.addAll(Collection<? extends E> c)
說明:將Collection c的全部元素添加到ArrayList中
源碼解釋:
-
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;
-
}
22.addAll(int index, Collection<? extends E> c)
說明:從第index位開始,將c全部拷貝到ArrayList
源碼解釋:
-
public boolean addAll(int index, Collection<? extends E> c) {
-
-
rangeCheckForAdd(index);
-
-
Object[] a = c.toArray();
-
int numNew = a.length;
-
-
ensureCapacityInternal(size + numNew);
-
-
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;
-
}
24.batchRemove(Collection<?> c, boolean complement)
說明:根據complement值,將ArrayList中包含c中元素的元素刪除或者保留
源碼解釋:
-
private boolean batchRemove(Collection<?> c, boolean complement) {
-
final Object[] elementData = this.elementData;
-
-
int r = 0, w = 0;
-
boolean modified = false;
-
try {
-
-
for (; r < size; r++)
-
-
if (c.contains(elementData[r]) == complement)
-
-
elementData[w++] = elementData[r];
-
} finally {
-
-
if (r != size) {
-
-
System.arraycopy(elementData, r,
-
elementData, w,
-
size - r);
-
-
w += size - r;
-
}
-
if (w != size) {
-
-
for (int i = w; i < size; i++)
-
elementData[i] = null;
-
modCount += size - w;
-
-
size = w;
-
modified = true;
-
}
-
}
-
return modified;
-
}
25.removeAll(Collection<?> c)
說明:ArrayList移除c中的所有元素
源碼解釋:
-
public boolean removeAll(Collection<?> c) {
-
-
Objects.requireNonNull(c);
-
-
return batchRemove(c, false);
-
}
26.retainAll(Collection<?> c)
說明:和removeAll相反,僅保留c中所有的元素
源碼解釋:
-
public boolean retainAll(Collection<?> c) {
-
Objects.requireNonNull(c);
-
-
return batchRemove(c, true);
-
}
27.iterator()
說明:返回一個Iterator對象,Itr爲ArrayList的一個內部類,其實現了Iterator<E>接口
代碼解釋:
-
public Iterator<E> iterator() {
-
return new Itr();
-
}
28.listIterator()
說明:返回一個ListIterator對象,ListItr爲ArrayList的一個內部類,其實現了ListIterator<E> 接口
源碼解釋:
-
public ListIterator<E> listIterator() {
-
return new ListItr(0);
-
}
29.listIterator(int index)
說明:返回一個從index開始的ListIterator對象
源碼解釋:
-
public ListIterator<E> listIterator(int index) {
-
if (index < 0 || index > size)
-
throw new IndexOutOfBoundsException("Index: "+index);
-
return new ListItr(index);
-
}
30.subList(int fromIndex, int toIndex)
說明:根據兩個參數,獲取到一個子序列
源碼解釋:
-
public List<E> subList(int fromIndex, int toIndex) {
-
-
subListRangeCheck(fromIndex, toIndex, size);
-
-
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的數組進行的,並沒有創建新的數組。
最後一個比較個人比較少接觸,大家需要自行度娘。
End
筆者技術真的是一般般,寫這個爲了加深理解的同時給害怕看源代碼的朋友一點鼓勵,所以筆者在寫的過程中有查閱很多資料來努力減少錯誤,但是如有錯漏之處,希望大神們指出,我會第一時間修改,以免誤人子弟,也希望和筆者一樣基礎不夠好的朋友不要畏懼看源碼,源碼看起來並不會很難,而且多看源代碼會對Java更深刻的理解。