Java源碼解讀之util.ArrayList
ArrayList是List接口的一個可變長數組實現。實現了所有List接口的操作,并允許存儲null值。除了沒有進行同步,ArrayList基本等同于Vector。在Vector中幾乎對所有的方法都進行了同步,但ArrayList僅對writeObject和readObject進行了同步,其它比如add(Object)、remove(int)等都沒有同步。
1.存儲
ArrayList使用一個Object的數組存儲元素。
private transient Object elementData[]; |
ArrayList實現了java.io.Serializable接口,這兒的transient標示這個屬性不需要自動序列化。下面會在writeObject()方法中詳細講解為什么要這樣作。
2.add和remove
public boolean add(Object o) { ensureCapacity(size + 1); // Increments modCount!! elementData[size++] = o; return true; } |
注意這兒的ensureCapacity()方法,它的作用是保證elementData數組的長度可以容納一個新元素。在“自動變長機制”中將詳細講解。
public Object remove(int index) { RangeCheck(index); modCount++; Object oldValue = elementData[index]; int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // Let gc do its work return oldValue; } |
RangeCheck()的作用是進行邊界檢查。由于ArrayList采用一個對象數組存儲元素,所以在刪除一個元素時需要把后面的元素前移。刪除一個元素時只是把該元素在elementData數組中的引用置為null,具體的對象的銷毀由垃圾收集器負責。
modCount的作用將在下面的“iterator()中的同步”中說明。
注:在前移時使用了System提供的一個實用方法:arraycopy(),在本例中可以看出System.arraycopy()方法可以對同一個數組進行操作,這個方法是一個native方法,如果對同一個數組進行操作時,會首先把從源部分拷貝到一個臨時數組,在把臨時數組的元素拷貝到目標位置。
3.自動變長機制
在實例化一個ArrayList時,你可以指定一個初始容量。這個容量就是elementData數組的初始長度。如果你使用:
ArrayList list = new ArrayList(); |
則使用缺省的容量:10。
public ArrayList() { this(10); } |
ArrayList提供了四種add()方法,
public boolean add(Object o) public void add(int index, Object element) public boolean addAll(Collection c) public boolean addAll(int index, Collection c) |
在每一種add()方法中,都首先調用了一個ensureCapacity(int miniCapacity)方法,這個方法保證elementData數組的長度不小于miniCapacity。ArrayList的自動變長機制就是在這個方法中實現的。
public void ensureCapacity(int minCapacity) { modCount++; int oldCapacity = elementData.length; if (minCapacity > oldCapacity) { Object oldData[] = elementData; int newCapacity = (oldCapacity * 3)/2 + 1; if (newCapacity < minCapacity) newCapacity = minCapacity; elementData = new Object[newCapacity]; System.arraycopy(oldData, 0, elementData, 0, size); } } |
從這個方法實現中可以看出ArrayList每次擴容,都擴大到原來大小的1.5倍。
每種add()方法的實現都大同小異,下面給出add(Object)方法的實現:
public boolean add(Object o) { ensureCapacity(size + 1); // Increments modCount!! elementData[size++] = o; return true; } |