一、.ArrayList:
寫過的項目到現(xiàn)在基本上面向業(yè)務(wù)域查詢返回大列表都是使用ArrayList來存儲業(yè)務(wù)數(shù)據(jù)的。
定義:ArrayList是List接口的可變數(shù)組的實現(xiàn)。實現(xiàn)了所有的可選列表的操作并允許包括null在內(nèi)的所有元素。除了實現(xiàn)List接口外,此類還提供一些方法來操作內(nèi)部用來存儲列表的數(shù)組的大小。
每個ArrayList實例都有一個容量,該容量是指來存儲列表元素的數(shù)組的大小,該容量至少等于列表數(shù)組的大小,隨著ArrayList的不斷添加元素,其容量也在自動增長,自動增長會將原來數(shù)組的元素向新的數(shù)組進行copy。因此,如果根據(jù)業(yè)務(wù)場景來提前預(yù)判數(shù)據(jù)量的大小。可在構(gòu)造ArrayList時指定其容量。在添加大量元素前,應(yīng)用程序可以使用ensureCapacity操作來增加ArrayList實例的容量,這樣就可以減少遞增式再分配數(shù)量的操作。
注意:我們都知道ArrayList不是線程安全的,如果存在多線程訪問ArrayList實例的場景,其中一個線程要在改變ArrayList列表結(jié)構(gòu)之前,需要先對它這個操作保持線程同步。

ArrayList繼承了AbstractList抽象類并實現(xiàn)了List接口,底層使用數(shù)組保存所有元素。

AbstractList主要作用是定義抽象對數(shù)組操作的公共主要行為,供具備相似功能的子類來具體實現(xiàn)自己特定的邏輯。
二、初始化
public ArrayList();默認(rèn)的構(gòu)造器,將會以默認(rèn)的大小來初始化內(nèi)部的數(shù)組
public ArrayList(int initialCapacity);用指定的大小來初始化內(nèi)部的數(shù)組
public ArrayList(Collectio<? extends E> c);用一個ICollection對象來構(gòu)造,并將該集合的元素添加到ArrayList
public ArrayList();默認(rèn)的構(gòu)造器
/**
* Shared empty array instance used for empty instances.
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
super();
this.elementData = EMPTY_ELEMENTDATA;
}
我本地JDK1.7 默認(rèn)數(shù)組長度是0,JDK1.6初始化大小是10
(1)添加元素,確定內(nèi)部容量
/**
* Default initial capacity.
*/
private static final int DEFAULT_CAPACITY = 10;
/** * Appends the specified element to the end of this list. * * @param e element to be appended to this list * @returntrue(as specified by {@link Collection#add}) */?
?public boolean add(E e) {?
?ensureCapacityInternal(size + 1); //確保內(nèi)部容量,判斷當(dāng)前容量大小,如果不夠就通過擴容來確保容量;size大小表示執(zhí)行添加元素之前的元素個數(shù),并不是ArrayList的容量,容量是elementData數(shù)組長度
?// Increments modCount!!?
?elementData[size++] = e;?
?return true;
?}
下面關(guān)注下ensureCapacityInternal(size + 1)是如何擴容的。
private void ensureCapacityInternal(int minCapacity) {
//如果實際存儲數(shù)組是空數(shù)組,則最小的容量是默認(rèn)容量,JDK1.7是10
if (elementData == EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
//如果數(shù)組長度elementData.length小于最小容量就需要擴容
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
以上,elementData是用來存儲實際數(shù)據(jù)的數(shù)組,minCapacity是最小的擴容容量。
三.擴容(重點)
/**
* 增加容量,以確保它至少能容納由最小容量參數(shù)指定的元素數(shù)
* @param minCapacity 所需要的最小容量
*/
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
//?int newCapacity = oldCapacity + oldCapacity * 0.5 也就是擴容了1.5倍
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//?MAX_ARRAY_SIZE:private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
// 這個最大值用來分配給數(shù)組的,由于不同的JVM需要在數(shù)組中需要存放些頭部信息,如果分配過大可能會導(dǎo)致內(nèi)存溢出:提示請求的數(shù)組大小超過了JVM限制
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
// 將獲取到的擴容的容量復(fù)制當(dāng)前到當(dāng)前數(shù)組
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;
}
總結(jié):ArrayList是采取延遲分配對象數(shù)組大小空間的,當(dāng)?shù)谝淮翁砑釉貢r才會分配10個對象空間,當(dāng)添加第11個元素的時候,會擴容1.5倍,當(dāng)添加到16個元素的時候擴容為15*1.5=22,以此類推。
ArrayList每次擴容都是通過Arrays.copyof(elementData, newCapacity)來實現(xiàn)的。
當(dāng)我們在明確對象的大致數(shù)目時候提前指定初始化數(shù)組的大小是一個非常明智的選擇。