top
Loading...
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;
}

作者:http://www.zhujiangroad.com
來源:http://www.zhujiangroad.com
北斗有巢氏 有巢氏北斗