java集合類源碼學習三——ArrayList
ArrayList無疑是java集合類中的一個巨頭,而且或許是使用最多的集合類。ArrayList繼承自AbstractList抽象類,實現了List<E>, RandomAccess, Cloneable, java.io.Serializable這些接口,這意味著ArrayList可以隨機取數據,支持淺拷貝和序列化。ArrayList可以存放各種類型的值,有序、可重復而且可以存放null,這里的有序指的是按順序存放,而不是自動排序。它有一個默認容量DEFAULT_CAPACITY = 10,還定義了兩個空數組EMPTY_ELEMENTDATA和DEFAULTCAPACITY_EMPTY_ELEMENTDATA,同樣都是靜態私有不可變的Object數組,那么為什么要弄兩個,從取名上看EMPTY_ELEMENTDATA指的是空數組,而DEFAULTCAPACITY_EMPTY_ELEMENTDATA指的是默認容量的未存放元素的空數組。從后面的代碼可以看出,給數組長度賦默認值之前,是與DEFAULTCAPACITY_EMPTY_ELEMENTDATA比較的,而讓數組為空數組則是與EMPTY_ELEMENTDATA比較的,如果非要說有差別,也就這點了,有點脫褲子放屁的意味。然后定義了一個object數組elementData,用transient修飾的,表示不可以被序列化,這就是ArrayList的底層實現,本質是個數組。提供了三個構造器,一個無參,一個可指定長度,還有一個可將其他Collection的集合轉化成ArrayList,下面是第三個構造器的代碼
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;
}
}
里面有個判斷class的操作,用于把從其他集合轉到數組的非Object類型轉化成Object類型數組。ArrayList底層既然是數組,那么最大長度也就為Integer的最大值減8,同樣在擴容的時候如果這個長度不夠,可以用hugeCapacity,也即Integer的最大值。下面是插入到一個位置和獲取一個位置的值的代碼
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 get(int index) {
rangeCheck(index);
return elementData(index);
}
可以看到,插入元素需要把該位置及后面的元素全部往后移一位,時間復雜度為O(n),而獲取一個元素,只需要根據索引定位過去就行,時間復雜度為O(1)。其余的操作基本就是各種對數組的操作,每次操作都會有一個modCount++,表示修改過一次,用的最多的方法System.arraycopy(Object src, int srcPos,Object dest, int destPos,int length),這是一個native方法,用于快速拷貝一段數組到另一個位置。后面還有迭代器Iterator和listIterator的具體實現,這個之前也分析過了,沒什么區別。
后面還有些JDK1.8加的支持函數式編程的方法,先不提。由于ArrayList的方法不是同步的,因此在多線程訪問的時候如果有對其進行操作,不是線程安全的。所以在多線程用的時候需要加個同步鎖,或者別的線程安全的集合類。

浙公網安備 33010602011771號