Java數組擴容:ArrayList自動擴容原理,初學者必知

在Java中,數組一旦創建,長度就是固定的。如果你嘗試添加超過數組長度的元素,就會拋出“數組索引越界”異常。而ArrayList作爲動態數組,完美解決了這個問題——它能根據元素數量自動擴容,不需要手動處理數組長度。下面我們一步步揭開ArrayList自動擴容的神祕面紗。

爲什麼需要數組擴容?

想象你有一個固定大小的盒子,最多隻能裝5個蘋果。當你想裝第6個蘋果時,盒子就“滿了”,這時候你要麼換個更大的盒子,要麼把蘋果扔掉。在Java中,普通數組就像這個“固定盒子”,而ArrayList則像一個會“自動換更大盒子”的智能容器。

ArrayList是什麼?

ArrayList是Java集合框架中的一個動態數組,它內部維護了一個數組(elementData)和一個變量(size,記錄當前元素個數)。當你添加元素時,ArrayList會自動檢查數組是否已滿,如果滿了就擴容,讓你可以繼續添加。

ArrayList如何自動擴容?

ArrayList的擴容核心是兩個步驟:觸發條件擴容過程

1. 觸發條件:數組已滿

當調用add()方法添加元素時,ArrayList會先檢查當前元素數量(size)是否等於數組長度(elementData.length)。如果相等,說明數組已滿,需要擴容。

2. 擴容過程:換一個更大的盒子

擴容時,ArrayList會執行以下操作:
- 計算最小容量:需要的最小容量是當前元素數量+1(比如已有10個元素,再添加1個,需要至少11個位置)。
- 計算新容量
- 如果是第一次擴容(默認構造ArrayList()),新容量直接設爲10(JDK默認初始容量)。
- 其他情況,新容量是原容量的1.5倍(例如原容量10,擴容後15;原容量15,擴容後22)。
- 複製元素:將原數組的元素複製到新容量的數組中,然後繼續使用新數組。

舉個例子:模擬擴容過程

我們用一個簡單的例子模擬ArrayList的擴容:

場景:創建一個無參構造的ArrayList,逐步添加元素,觀察容量變化。

  1. 初始狀態elementData數組長度爲0(空數組),size=0
  2. 添加第1個元素
    - size=0,數組已滿(elementData.length=0),觸發擴容。
    - 首次擴容,新容量=10(默認容量)。
    - 數組變爲長度10,size=1
  3. 添加第11個元素
    - size=10,數組已滿(elementData.length=10),觸發擴容。
    - 原容量=10,新容量=10 + 10/2 = 15(1.5倍)。
    - 數組變爲長度15,size=11
  4. 添加第16個元素
    - size=15,數組已滿(elementData.length=15),觸發擴容。
    - 原容量=15,新容量=15 + 15/2 = 22(1.5倍)。
    - 數組變爲長度22,size=16

規律:每次擴容後容量約爲原來的1.5倍,首次擴容到10,後續每次增加1.5倍。

爲什麼擴容因子是1.5倍?

1.5倍是一個平衡選擇:
- 太小:每次擴容太少(如1.1倍),會頻繁擴容,複製數組的次數增多,性能下降。
- 太大:每次擴容太多(如2倍),會浪費內存(空出大量未使用的空間)。
- 1.5倍:既能減少擴容次數,又能避免內存浪費,是JDK經過優化後的結果。

理解擴容原理的好處

  • 避免數組越界:知道ArrayList會自動擴容,就不用擔心添加元素時數組長度不夠。
  • 優化性能:如果能預估元素數量,創建時指定初始容量(如new ArrayList(100)),可以減少擴容次數,提升效率。
  • 掌握底層邏輯:理解擴容原理後,能更清晰地使用ArrayList進行開發,寫出更健壯的代碼。

總結

ArrayList的自動擴容原理本質是動態數組:當數組容量不足時,創建一個新的、容量更大的數組,將原元素複製到新數組中,從而實現“自動變長”。擴容因子約爲1.5倍,首次擴容到10(默認構造)。掌握這一原理,能讓你在使用ArrayList時更得心應手,避免常見問題。

記住:ArrayList不是無限大的,它的擴容需要消耗資源(複製數組),所以如果能提前預估元素數量,設置初始容量會更高效哦!

小夜