ArrayList是java中非常常用的一個(gè)類枕赵,它可以實(shí)現(xiàn)一個(gè)無限長(zhǎng)度的數(shù)組谷扣。由于一般的List的長(zhǎng)度(即容量)是有限的渣蜗,所以ArrayList的擴(kuò)容是一個(gè)非常被容易問到的點(diǎn)报嵌。
當(dāng)面試被問到這個(gè)問題的時(shí)候,最好的解決方法就是詢求查看源代碼贡未,因?yàn)閖dk的文檔設(shè)計(jì)的可讀性非常高种樱,通過查看文檔可以很好的回答這個(gè)問題。
- 進(jìn)入ArrayList文檔中的add方法
擴(kuò)容的實(shí)現(xiàn)俊卤,是什么時(shí)候需要用到的呢嫩挤?答案非常簡(jiǎn)單,就是當(dāng)你往列表中增加新的元素的時(shí)候才需要消恍。jdk中ArrayList.add()如下:
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
其中調(diào)用了ensureCapacityInternal
這個(gè)方法岂昭。這個(gè)方法翻譯為中文意思為確保容量足夠,看方法名就知道這個(gè)方法和擴(kuò)容有關(guān)狠怨,因此要進(jìn)入這個(gè)方法繼續(xù)查看约啊。
- 進(jìn)入
ensureCapacityInternal
方法
源代碼如下:
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
這個(gè)方法很簡(jiǎn)單邑遏,直接調(diào)用了另一個(gè)方法ensureExplicitCapacity
(確保明確的容量),因此我們進(jìn)入這個(gè)方法繼續(xù)看看。
- 進(jìn)入
ensureExplicitCapacity
方法
源代碼如下:
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
到這里棍苹,我們終于很接近答案了无宿,里面有一行注釋,中文意思大概是容量溢出的代碼枢里,里面經(jīng)過一個(gè)判斷后調(diào)用了grow方法孽鸡,這應(yīng)該就是答案栏豺,因此點(diǎn)進(jìn)去看看彬碱。
- 進(jìn)入
grow
方法
代碼如下
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);
}
翻譯起來就是,把原來list的長(zhǎng)度作為舊的容量:int oldCapacity = elementData.length;
新的容量為舊的容量加上舊的容量的右移一位(涉及位運(yùn)算奥洼,就是原來容量的0.5倍):int newCapacity = oldCapacity + (oldCapacity >> 1);
創(chuàng)建一個(gè)長(zhǎng)度為新容量的ArrayList巷疼,然后把舊的都copy過去,從而實(shí)現(xiàn)擴(kuò)容灵奖。