面試可能會聊到ArrayList的擴容機制:首次分配大小爲10的一個容量,超過10的容量那麼就會以1.5倍擴容
舉個通俗的例子:你是個老闆,最開始你有5個員工分別要住5個房間,ArrayList很大方,首次就直接分配10個房間給你。後來你的事業蒸蒸日上,你的員工越來越多,有11個員工了,住不下原來的10個房間,那麼我ArrayList以原來已經住的房間(10個的房間)的1.5倍方式開房間給你員工住。
結合上面列子和下面的圖,可能會讓你更加深理解
(原來10個房間 × 1.5 = 15房間,15個房間 × 1.5 = 22房間)
代碼實例
首先創建一個ArrayList,調用add,然後點擊add方法裏面的源碼看看究竟吧!
ArrayList<String> arraylist = new ArrayList<String>();
arraylist.add("hello");
可以看到add的一個函數,它先調用ensureCapacityInternal,是不是不知道它是幹啥的,從字面意思理解的話是確保容量足夠的,再點擊看它的源碼
public boolean add(E e) {
ensureCapacityInternal(size + 1);
elementData[size++] = e;
return true;
}
嗯…我去,又調了一個ensureExplicitCapacity,還有calculateCapacity,那就先看看
calculateCapacity
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
它會判斷數組是否爲空,如果爲空,首次分配容量的值爲10,它的常量:DEFAULT_CAPACITY = 10(這裏確保容量足夠)
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
接下來調用ensureExplicitCapacity,判斷當數據大於當前數組,那麼調用grow
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
實現擴容的方法正是:grow
主要gorw方法裏這句,oldCapacity右移1(相當於除以2),再加上oldCapacity(可以理解就是1.5倍)賦值給newCapacity。如果擴展還是小於minCapacity,就擴展minCapacity
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity -minCapacity < 0)
newCapacity = minCapacity;
最後
你會發現看源碼有點像剝洋蔥,一層層的剝,不知道到什麼時候你已經淚流滿面了,當然只是個ArrayList還不至於啦