這裏擴容指的是無參構造初始化時的場景。對於指定集合長度的構造函數初始化時,初始容量爲指定長度,容量不夠時再擴容爲原來的 1.5 倍。java
下面主要介紹無參構造初始化時的場景。數組
參數定義:安全
transient Object[] elementData; // 實際存儲數據的數組緩衝區 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; // 初始數組
默認初始化很是簡單,調用無參構造器,初始化一個空數組。真正擴容的邏輯在每次添加元素執行。函數
/** * Constructs an empty list with an initial capacity of ten. */ public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }
添加方法:this
public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; }
size:ArrayList 的長度,可用 List#size() 獲取線程
添加方法一共作了兩件事:3d
添加元素不用多說,向數組中的下一個位置插入便可。下面着重介紹容量判斷的邏輯:code
1. 判斷容量大小對象
首先判斷當前集合容量大小是否足夠,若是不夠就調用擴容方法 grow(int minCapacity)。blog
// 確保集合能夠添加下一個元素 minCapacity:當前須要的最小容量 private void ensureCapacityInternal(int minCapacity) { ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); } // 計算添加元素須要的最小容量 private static int calculateCapacity(Object[] elementData, int minCapacity) { // 若是當前集合爲空,判斷所需最小容量和默認容量大小,返回較大值 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { return Math.max(DEFAULT_CAPACITY, minCapacity); } return minCapacity; } // 確保集合能夠知足須要的最小容量 private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); }
2. 擴容方法
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); }
首先初始化一個 ArrayList,向裏面循環添加 11 個元素。下面針對於第一次添加和第11次添加分別查看 數組初始化 和 數組擴容的邏輯。
public static void main(String[] args) { List<string> list = new ArrayList<>(); for (int i = 0; i < 11; i++) { list.add("items"); } }
ArrayList 初始化後,底層會初始化一個空的對象數組 (elementData),長度 (size) 爲 0。當第一次添加元素時,會將其初始化爲一個長度爲 10 的數組。下面看第一次添加元素的流程:
1.進入添加方法 add(E e)
2.判斷容量大小
3.計算所需最小容量
當前數組爲空數組,因此if 條件成立,DEFAULT_CAPACITY = 10,minCapacity = 1;
當前方法返回 10;
4.判斷數組是否擴容
elementData 當前爲空數組,length = 0;minCapacity 爲上一步返回的 10;因此此處會調用擴容方法 grow()
5.數組擴容(初始化數組)
這裏會根據上面指定的默認容量 10 來給數組擴容。
6.添加元素
根據以前程序的運行,集合保存數據的數組在第一次添加元素時擴充容量爲 10,因此在第 11 次添加元素時就會調用擴容的邏輯。
一、add() 方法
minCapacity = size + 1 = 11;
二、判斷容量大小
三、計算所需最小容量
非第一次 直接返回
四、判斷是否擴容
所需最小容量大於數組長度,調用擴容方法。
五、擴容
六、添加元素