轉載自:http://www.cnblogs.com/skywang12345/p/3308556.html
第1部分 ArrayList介紹
ArrayList簡介
ArrayList 是一個數組隊列,相當於 動態數組。與Java中的數組相比,它的容量能動態增長。它繼承於AbstractList,實現了List, RandomAccess, Cloneable, java.io.Serializable這些接口。
ArrayList 繼承了AbstractList,實現了List。它是一個數組隊列,提供了相關的添加、刪除、修改、遍歷等功能。
ArrayList 實現了RandmoAccess接口,即提供了隨機訪問功能。RandmoAccess是java中用來被List實現,爲List提供快速訪問功能的。在ArrayList中,我們即可以通過元素的序號快速獲取元素對象;這就是快速隨機訪問。稍後,我們會比較List的“快速隨機訪問”和“通過Iterator迭代器訪問”的效率。
ArrayList 實現了Cloneable接口,即覆蓋了函數clone(),能被克隆。
ArrayList 實現java.io.Serializable接口,這意味着ArrayList支持序列化,能通過序列化去傳輸。
和Vector不同,ArrayList中的操作不是線程安全的!所以,建議在單線程中才使用ArrayList,而在多線程中可以選擇Vector或者CopyOnWriteArrayList。
ArrayList構造函數// 默認構造函數
ArrayList()
// capacity是ArrayList的默認容量大小。當由於增加數據導致容量不足時,容量會添加上一次容量大小的一半。
ArrayList(int capacity)
// 創建一個包含collection的ArrayList
ArrayList(Collection<? extends E> collection)ArrayList的API
ArrayList的API
// Collection中定義的API
boolean add(E object)
boolean addAll(Collection<? extends E> collection)
void clear()
boolean contains(Object object)
boolean containsAll(Collection<?> collection)
boolean equals(Object object)
int hashCode()
boolean isEmpty()
Iterator<E> iterator()
boolean remove(Object object)
boolean removeAll(Collection<?> collection)
boolean retainAll(Collection<?> collection)
int size()
<T> T[] toArray(T[] array)
Object[] toArray()
// AbstractCollection中定義的API
void add(int location, E object)
boolean addAll(int location, Collection<? extends E> collection)
E get(int location)
int indexOf(Object object)
int lastIndexOf(Object object)
ListIterator<E> listIterator(int location)
ListIterator<E> listIterator()
E remove(int location)
E set(int location, E object)
List<E> subList(int start, int end)
// ArrayList新增的API
Object clone()
void ensureCapacity(int minimumCapacity)
void trimToSize()
void removeRange(int fromIndex, int toIndex)
第2部分 ArrayList數據結構
ArrayList的繼承關係
java.lang.Object
↳ java.util.AbstractCollection<E>
↳ java.util.AbstractList<E>
↳ java.util.ArrayList<E>
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable {}
ArrayList與Collection關係如下圖:
ArrayList包含了兩個重要的對象:elementData 和 size。
(01) elementData 是"Object[]類型的數組",它保存了添加到ArrayList中的元素。實際上,elementData是個動態數組,我們能通過構造函數 ArrayList(int initialCapacity)來執行它的初始容量爲initialCapacity;如果通過不含參數的構造函數ArrayList()來創建ArrayList,則elementData的容量默認是10。elementData數組的大小會根據ArrayList容量的增長而動態的增長,具體的增長方式,請參考源碼分析中的ensureCapacity()函數。
(02) size 則是動態數組的實際大小。
第3部分 ArrayList源碼解析(JDK1.8)
add(E e) 方法
//添加一個對象到尾部
public boolean add(E e) {
//確保當前容量足夠,不夠則進行擴容操作
ensureCapacityInternal(size + 1); // Increments modCount!!
//設置值e
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
//ArrayList爲空時,容量直接擴容爲10
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
//當前需要容量不足DEFAULT_CAPACITY(10)時,直接擴爲10
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
//確保得到明確需要新容量
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
//“發生結構”時+1,防止遍歷元素時,發生結構變更,則拋錯。
modCount++;
// 需要容量大於當前容量時,執行擴容操作
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
擴容規則
//minCapacity 當前需要的最小容量
private void grow(int minCapacity) {
// 當前容量
int oldCapacity = elementData.length;
//新容量=當前容量+當前容量的1/2
int newCapacity = oldCapacity + (oldCapacity >> 1);
//當新容量還是小於minCapacity時,則直接擴從至minCapacity大小
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//當newCapacity大於MAX_ARRAY_SIZE(Integer.MAX_VALUE - 8)時
if (newCapacity - MAX_ARRAY_SIZE > 0)
// 容量過於巨大,需判斷是否發生溢出
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
// 本質還是調用Arrays內方法,完成對數組的操作!
elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // 發生內存溢出,
throw new OutOfMemoryError();
//未發生溢出,則返回 Integer.MAX_VALUE 或 MAX_ARRAY_SIZE
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
(1)對於空的ArrayList,首次添加元素的時候,就會直接擴容至10
(2)所需容量大於當前容量時,進行擴容,擴容至當前容量的1.5倍
(3)如果擴容完後還是所需容量還是大於當前容量,直接擴容至所需容量
clear方法
public void clear() {
modCount++;
// clear to let GC do its work
for (int i = 0; i < size; i++)
elementData[i] = null;
size = 0;
}
置elementData中的所有值爲null,注意不會更改elementData的大小,如果需要釋放,需要調用trimToSize方法