ArrayList源碼解讀二之add、set、get、remove

在看add、set源碼之前,我們先看幾個重要的函數,add、set、remove、get都會調用它。

<code>   private void ensureCapacityInternal(int minCapacity) {//add、set、remove、get先都會調用此方法
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}//minCapacity是添加元素後數組大小 /<code>
<code>\tprivate static int calculateCapacity(Object[] elementData, int minCapacity) {//獲取數組大小
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
{//創建無參構造器時候會把DEFAULTCAPACITY_EMPTY_ELEMENTDATA指向elementData
return Math.max(DEFAULT_CAPACITY, minCapacity);
}//當創建無參構造時候才會有用到,默認值為10
return minCapacity;
}/<code>
<code>    private void ensureExplicitCapacity(int minCapacity) {
modCount++;//記錄修改次數
if (minCapacity - elementData.length > 0)//當添加元素後數組大小大於原來數組大小長度
grow(minCapacity);//擴容函數
}/<code>
<code>    private void grow(int minCapacity) {//擴容函數
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);//擴容1.5倍
if (newCapacity - minCapacity < 0)//當添加元素後數組大於擴容後的倍數時
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)//當數組遠遠大於Array規範長度時候
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);//複製
}/<code>

- 一般情況進行擴容是1.5倍。

- 特殊情況:添加的元素後的數量遠超過擴容1.5倍的值時,會擴容添加元素的數量。

( 比如說:第一個ArrayList大小是10 第二個ArrayList大小為30 進行addALL函數操作的時候minCapacity的大小是30 遠遠超過擴容1.5倍後的數量)

**注意!!!許多在講arrayList擴容機制的時候只會說1.5倍 而不說特殊情況。**

看懂這些方法後接下來到add、set、get、remove函數就容易了。

**(相比add方法)set、get、remove函數可以選擇性看!!!!!!!!**

###1.ArrayList中的add函數。

####add函數

<code>    public boolean add(E e) {
ensureCapacityInternal(size + 1); //進行擴容機制
elementData[size++] = e;//進行賦值
return true;
}/<code>
<code>    public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1);
System.arraycopy(elementData, index, elementData, index + 1,size - index);
elementData[index] = element;
size++;
}/<code>

add 2個方法基本操作差不多

1. rangeCheckForAdd是判斷index是否超過elementData的大小,是則拋出越界異常。

2. ensureCapacityInternal是上面提到判斷調用的函數,最主要是進行擴容機制。

3. System.arraycopy是為直接原數組index後面的值往後移一位如圖顯示。

4. 賦值。

5. 記錄元素數量,並且+1。


ArrayList源碼解讀二之add、set、get、remove

移動數組操作

###2.ArrayList中的set函數。

####set函數

<code>    public E set(int index, E element) {
rangeCheck(index);//是否檢查越界
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}/<code>

- 首先獲取到elementData的index舊元素

- 將新的element值賦予index

- 返回給OldValue**

###3.ArrayList中的get函數。

####get函數

<code>    public E get(int index) {
rangeCheck(index);
return elementData(index);
}/<code>

**1. 獲取到element(index)的位置元素返回。**

###4.ArrayList中的remove函數。

####remove函數

<code>    public E remove(int index) {
rangeCheck(index);
modCount++;

E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,numMoved);
elementData[--size] = null;
return oldValue;
}/<code>

- 首先獲取到elementData的index舊元素

- 獲取index後面需要移動的位置

- System.arraycopy進行移動(與addAll差不多)

- 對空出來的元素進行賦值null值

- 返回舊值

結論:

- 無參構造在第一次添加元素時候進行擴容後容量會是10。

- 擴容機制一般情況是1.5倍,特殊情況(添加元素大於擴容1.5倍的時候)是擴容為添加元素本身大小。

- 指定位置index操作元素時候都會進行越界檢查、並且會對數組進行移動操作。


分享到:


相關文章: