arrayList源碼解析

public class ArrayList<E> extends AbstractList<E>  

implements List<E>, RandomAccess, Cloneable, java.io.Serializable 

 

0.ArrayList元素定義:

//存儲數組元素的緩衝區;也就是真實的ArrayList的盒子大小

transient Object[] elementData;

//默認空數組元素

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

//默認初始化容量

private static final int DEFAULT_CAPACITY = 10;

//數組的大小,也就是真實ArrayList裏面存的東西多少

private int size;

//記錄被修改的次數

protected transient int modCount = 0;

//數組的最大值

private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8

 

1.ArrayList的構造函數:

無參構造函數:

public ArrayList() {

//初始化一個空的數組,在JDK1.8以後默認數組長度10,不在構造函數時創建,實在add操作時初始化

this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;

}

定義長度的構造函數:

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);

}

}

輸入集合的構造函數:

public ArrayList(Collection<? extends E> c) {

//將集合定義爲數組複製給緩衝區(arrayList底層)

elementData = c.toArray();

//集合不爲空

if ((size = elementData.length) != 0) {

//不爲空,如果類型不一樣,調用複製方法;將集合複製給新的arrayList

if (elementData.getClass() != Object[].class)

elementData = Arrays.copyOf(elementData, size, Object[].class);

} else {

//集合爲空;定義一個空數組

this.elementData = EMPTY_ELEMENTDATA;

}

}

2.添加元素add:

添加元素:

public boolean add(E e) {

//擴充長度,在原來的大小上面加1 

ensureCapacityInternal(size + 1); // Increments modCount!!

//添加元素

elementData[size++] = e;

return true;

}

或者

public void add(int index, E element) {

//判斷index是否越界

rangeCheckForAdd(index);

ensureCapacityInternal(size + 1); // Increments modCount!!

System.arraycopy(elementData, index, elementData, index + 1, size - index);

elementData[index] = element;

size++;

}

判斷是否越界:

private void rangeCheckForAdd(int index) {

//小於0或者大於size都數組越界

if (index > size || index < 0)

throw new IndexOutOfBoundsException(outOfBoundsMsg(index));

}

計算容量:

//minCapacit原本長度+1---》因爲新添加一個元素,肯定要默認長度+1

private void ensureCapacityInternal(int minCapacity) {

//如果這個數組等於空,返回最大的容量,否則,還是原來的容量+1 

if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {

minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);

}

ensureExplicitCapacity(minCapacity);

}

確認擴展容量

private void ensureExplicitCapacity(int minCapacity) {

//修改次數+1

modCount++;

// 如果容量不夠,調用增加容量方法

if (minCapacity - elementData.length > 0)

grow(minCapacity);

}

擴展方法

private void grow(int minCapacity) {

// 獲取原來數組容量的長度,老的數組長度

int oldCapacity = elementData.length;

//新增加的容量長度爲原來容量的1.5倍 

int newCapacity = oldCapacity + (oldCapacity >> 1);

//新的容量小於需要的容量;那麼新的容量=需要的容量

if (newCapacity - minCapacity < 0)//只有之前該list爲空的情況,才創建list長度爲10

newCapacity = minCapacity;

//新創建的容量(1.5)超過數組的最大值。按照最大的長度創建list

if (newCapacity - MAX_ARRAY_SIZE > 0)

newCapacity = hugeCapacity(minCapacity);//爲數組的最大值

// 調用複製方法,在原來元素上增加容量,這就是傳說中的可變集合。用新長度複製原數組

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;

}

具體的複製方法

public static <T,U> T[] copyOf(U[] original, int newLength,

Class<? extends T[]> newType) {

@SuppressWarnings("unchecked")

獲得者數組對象(創建一個長度爲1.5oldLength的新數組)

T[] copy = ((Object)newType == (Object)Object[].class)

? (T[]) new Object[newLength]

: (T[]) Array.newInstance(newType.getComponentType(), newLength);

 

調用系統的方法增加數組容量;(將老的數組複製到新數組中。)

System.arraycopy(original, 0, copy, 0,Math.min(original.length, newLength));

return copy;

}

3.當ArrayList中有空閒的空間時,縮減ArrayList的容量;應用程序可以使用這個方法最小化ArrayList實例

public void trimToSize() {

modCount++;//記錄修改次數

//判斷真實數組的長度是否小於擴容緩存的長度

if (size < elementData.length) {

//如果數組的大小爲0,則給該ArrayList定義爲空數組,否則按照真實的數組長度定義ArrayList容量長度

elementData = (size == 0)? EMPTY_ELEMENTDATA : Arrays.copyOf(elementData, size);

}

}

4.確定容量

public void ensureCapacity(int minCapacity) {

//最小擴容長度;如果該ArrayList不爲空;可以不進行擴容0;如果爲空就要進行默認長度10

int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) ? 0 : DEFAULT_CAPACITY;

 

if (minCapacity > minExpand) {

ensureExplicitCapacity(minCapacity);

}

}

5.ArrayList的克隆;因爲實現了Cloneable接口,所以支持克隆

//可以一個完全一樣的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);

}

}

6.刪除操作

/**

* 移除此列表中指定位置上的元素

* @param index 需被移除的元素的索引

* @return the element 被移除的元素值

* @throws IndexOutOfBoundsException {@inheritDoc}

*/

public E remove(int index) {

rangeCheck(index); //判斷index是否 <= size

 

modCount++;

E oldValue = elementData(index);

//將數組elementData中index位置之後的所有元素向前移一位

int numMoved = size - index - 1;

if (numMoved > 0)

System.arraycopy(elementData, index+1, elementData, index,

numMoved);

elementData[--size] = null; //將原數組最後一個位置置爲null,由GC清理

 

return oldValue;

}

 

//移除ArrayList中首次出現的指定元素(如果存在),ArrayList中允許存放重複的元素

public boolean remove(Object o) {

// 由於ArrayList中允許存放null,因此下面通過兩種情況來分別處理。

if (o == null) {

for (int index = 0; index < size; index++)

if (elementData[index] == null) {

fastRemove(index); //私有的移除方法,跳過index參數的邊界檢查以及不返回任何值

return true;

}

} else {

for (int index = 0; index < size; index++)

if (o.equals(elementData[index])) {

fastRemove(index);

return true;

}

}

return false;

}

 

//私有的刪除指定位置元素的方法,跳過index參數的邊界檢查以及不返回任何值

private void fastRemove(int index) {

modCount++;

int numMoved = size - index - 1;

if (numMoved > 0)

System.arraycopy(elementData, index+1, elementData, index,

numMoved);

elementData[--size] = null; // clear to let GC do its work

}

 

//清空ArrayList,將全部的元素設爲null

public void clear() {

modCount++;

 

// clear to let GC do its work

for (int i = 0; i < size; i++)

elementData[i] = null;

 

size = 0;

}

 

//刪除ArrayList中從fromIndex(包含)到toIndex(不包含)之間所有的元素,共移除了toIndex-fromIndex個元素

protected void removeRange(int fromIndex, int toIndex) {

modCount++;

int numMoved = size - toIndex; //需向前移動的元素的個數

System.arraycopy(elementData, toIndex, elementData, fromIndex,

numMoved);

 

// clear to let GC do its work

int newSize = size - (toIndex-fromIndex);

for (int i = newSize; i < size; i++) {

elementData[i] = null;

}

size = newSize;

}

 

//刪除ArrayList中包含在指定容器c中的所有元素

public boolean removeAll(Collection<?> c) {

Objects.requireNonNull(c); //檢查指定的對象c是否爲空

return batchRemove(c, false);

}

 

//移除ArrayList中不包含在指定容器c中的所有元素,與removeAll(Collection<?> c)正好相反

public boolean retainAll(Collection<?> c) {

Objects.requireNonNull(c);

return batchRemove(c, true);

}

 

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) //判斷指定容器c中是否含有elementData[r]元素

elementData[w++] = elementData[r];

} finally {

// Preserve behavioral compatibility with AbstractCollection,

// even if c.contains() throws.

if (r != size) {

System.arraycopy(elementData, r,

elementData, w,

size - r);

w += size - r;

}

if (w != size) {

// clear to let GC do its work

for (int i = w; i < size; i++)

elementData[i] = null;

modCount += size - w;

size = w;

modified = true;

}

}

return modified;

}

6.修改操作

 

//將指定索引上的值替換爲新值,並返回舊值

public E set(int index, E element) {

//檢查是否index越界

rangeCheck(index);

 

E oldValue = elementData(index);

elementData[index] = element;

return oldValue;

}

7.查找元素

//判斷ArrayList中是否包含Object(o)

public boolean contains(Object o) {

return indexOf(o) >= 0;

}

 

//正向查找,返回ArrayList中元素Object o第一次出現的位置,如果元素不存在,則返回-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;

}

 

//逆向查找,返回ArrayList中元素Object 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;

}

 

@SuppressWarnings("unchecked")

E elementData(int index) {

return (E) elementData[index];

}

 

//返回指定索引處的值

public E get(int index) {

rangeCheck(index);

 

return elementData(index); //實質上return (E) elementData[index]

}

8.序列化和反序列化

//序列化:將ArrayList的“大小,所有的元素值”都寫入到輸出流中

private void writeObject(java.io.ObjectOutputStream s)

throws java.io.IOException{

// Write out element count, and any hidden stuff

int expectedModCount = modCount;

s.defaultWriteObject();

 

// Write out size as capacity for behavioural compatibility with clone()

s.writeInt(size);

 

// Write out all elements in the proper order.

for (int i=0; i<size; i++) {

s.writeObject(elementData[i]);

}

 

if (modCount != expectedModCount) {

throw new ConcurrentModificationException();

}

}

 

//反序列化:先將ArrayList的“大小”讀出,然後將“所有的元素值”讀出

private void readObject(java.io.ObjectInputStream s)

throws java.io.IOException, ClassNotFoundException {

elementData = EMPTY_ELEMENTDATA;

 

// Read in size, and any hidden stuff

s.defaultReadObject();

 

// Read in capacity

s.readInt(); // ignored

 

if (size > 0) {

// be like clone(), allocate array based upon size not capacity

ensureCapacityInternal(size);

 

Object[] a = elementData;

// Read in all elements in the proper order.

for (int i=0; i<size; i++) {

a[i] = s.readObject();

}

}

}

9.其他方法:

 

//返回ArrayList的大小(元素個數)

public int size() {

return size;

}

 

//判斷ArrayList是否爲空

public boolean isEmpty() {

return size == 0;

}

 

//返回此 ArrayList實例的淺拷貝

public Object clone() {

try {

ArrayList<?> v = (ArrayList<?>) super.clone();

v.elementData = Arrays.copyOf(elementData, size);

v.modCount = 0;

return v;

} catch (CloneNotSupportedException e) {

// this shouldn't happen, since we are Cloneable

throw new InternalError(e);

}

}

//返回一個包含ArrayList中所有元素的數組

public Object[] toArray() {

return Arrays.copyOf(elementData, size);

}

 

//如果給定的參數數組長度足夠,則將ArrayList中所有元素按序存放於參數數組中,並返回

//如果給定的參數數組長度小於ArrayList的長度,則返回一個新分配的、長度等於ArrayList長度的、包含ArrayList中所有元素的新數組

@SuppressWarnings("unchecked")

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;

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章