1.從底層數據結構,擴容策略
2.ArrayList的增刪改查
3.特殊處理重點關注
4.遍歷的速度,隨機訪問和iterator訪問效率對比數組
對於第一個問題,底層即時一個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;索引
最後吧新的數據拷貝過來取代舊數據
進行add操做的時候支持2種添加方式
添加的時候size+1,做爲新的size,而後調用擴容策略
最後吧新數據放到最後一個位置,返回true
其次添加到指定位置
作了2次拷貝操做
1.先建立新的容納大小的空間
2.而後把須要添加進去的數據的index位置,日後推移拷貝一遍,而後再指定位置寫入
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
Remove(obj)刪除操做底層調用的仍是fastremove
根據要刪除的位置計算須要移動的元素個數
好比2個元素,如今要刪除第一個元素,那麼index=0,那麼就是2-0-1 = 1;須要移動一個
Index就是對應的元素的下標,numMoved就是須要移動的元素的個數
直接刪除索引
Remove(int)
刪除這個索引以前,會先判斷是否越界
和以前的刪除大同小異
修改,查詢就不說了,就是set和get操做,分別是elementData[index] = ele,和return elemenetData[index]
1.這裏注意ArrayList有一個modCount屬性,這個屬性用來標識這個list被修改了多少次
2.注意使用迭代器的時候,對元素的增長或者刪除,請用迭代器的刪除,而不能用list的remove,並且遍歷的時候只能刪除,不能作新增
這個方法會校驗
ExpectedModCount 而這個參數在建立iterator的時候,就進行了賦值 int expectedModCount = modCount;
並無差異,其實iterator也就是對數組訪問,因此不存在效率問題,只是咱們通常的狀況能夠進行隨機訪問,而iterator只能進行遍歷
這個就否了,不用管
https://www.zhihu.com/question/26603565
https://blog.csdn.net/fighterandknight/article/details/61240861