【數據結構】6.java源碼ArrayList

 關於ArrayList的源碼關注點

1.從底層數據結構,擴容策略
2.ArrayList的增刪改查
3.特殊處理重點關注
4.遍歷的速度,隨機訪問和iterator訪問效率對比
數組


1.從底層數據結構,擴容策略

對於第一個問題,底層即時一個object的數組,用來存放動態數據:
transient Object[] elementData;
默認初始容量大小是10個,注意這裏有個坑不是一開始就是10個,而是當進行add操做的時候,會默認修改成10個:private static final int DEFAULT_CAPACITY = 10;數據結構


源碼中進行初始化的時候:
多線程

 


而咱們的DEFAULTCAPACITY_EMPTY_ELEMENTDATA這個數據是,也就是說只進行new操做的時候,咱們是給了一個空的數組大小是0長度是0,大小是0
Private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};this

 這裏源碼中有一段代碼:spa

 

 

 

collection.toArray()應該等同於collection.toArray(new Object[0]),返回的是Object[]類型。然而,Arrays.asList卻不是這樣,若是它的類型是一個Object[]子類(好比String[]),那麼toArray()就會返回這個子類而不是Object[],因為它調用的是clone()).net

做者:楊寒
連接:https://www.zhihu.com/question/26603565/answer/33394672
來源:知乎
著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。線程

 

EnsureCapacityInternal 擴容策略最終調用======》grow方法進行大小增加code

只有在容量不夠了的時候纔會採起擴容措施blog

 

private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // minCapacity is usually close to size, so this is a win:
    elementData = Arrays.copyOf(elementData, newCapacity);
}

 

1.並且擴容也很簡單粗暴,直接擴大1.5倍,採用右移的方式進行擴容,而後加上原始容量
2.若是括了1.5倍,仍是比須要獲取的大小要小,那麼就直接把大小擴爲想要獲取的大小
3.若是擴容以後的大小,超出限制(Integer.MAX_VALUE - 8;),那麼就擴到最大Integer.MAX_VALUE,若是指望的大小還沒超過這個Integer.MAX_VALUE - 8;那麼就擴圍Integer.MAX_VALUE - 8;索引

最後吧新的數據拷貝過來取代舊數據

 

 

2.ArrayList的增刪改查


2.1 add操做

進行add操做的時候支持2種添加方式

 

 

 

 

 

添加的時候size+1,做爲新的size,而後調用擴容策略
最後吧新數據放到最後一個位置,返回true


其次添加到指定位置
作了2次拷貝操做
1.先建立新的容納大小的空間
2.而後把須要添加進去的數據的index位置,日後推移拷貝一遍,而後再指定位置寫入
System.arraycopy(elementData, index, elementData, index + 1,
size - index);

 

 

 

2.2 刪除remove(obj),remove(int),fastRemove

Remove(obj)刪除操做底層調用的仍是fastremove
根據要刪除的位置計算須要移動的元素個數

 

 

 

好比2個元素,如今要刪除第一個元素,那麼index=0,那麼就是2-0-1 = 1;須要移動一個
Index就是對應的元素的下標,numMoved就是須要移動的元素的個數

 

 

 

 

 

直接刪除索引
Remove(int)

刪除這個索引以前,會先判斷是否越界

 

 

和以前的刪除大同小異

 

修改,查詢就不說了,就是set和get操做,分別是elementData[index] = ele,和return elemenetData[index]

 

3.特殊處理重點關注,iterator

1.這裏注意ArrayList有一個modCount屬性,這個屬性用來標識這個list被修改了多少次
2.注意使用迭代器的時候,對元素的增長或者刪除,請用迭代器的刪除,而不能用list的remove,並且遍歷的時候只能刪除,不能作新增

 


這個方法會校驗

 

ExpectedModCount 而這個參數在建立iterator的時候,就進行了賦值 int expectedModCount = modCount;

 

 


4.遍歷的速度,隨機訪問和iterator訪問效率對比

並無差異,其實iterator也就是對數組訪問,因此不存在效率問題,只是咱們通常的狀況能夠進行隨機訪問,而iterator只能進行遍歷

 


5.是否支持多線程

這個就否了,不用管

 

 

 

借鑑:

https://www.zhihu.com/question/26603565
https://blog.csdn.net/fighterandknight/article/details/61240861

相關文章
相關標籤/搜索