前言
ArrayList 是 Java 最常用的動態陣列實現,基於物件陣列 Object[] elementData,支援隨機存取、自動擴容。本文系統整理核心 API、原理與效能優化。
1. 建構子
new ArrayList() // 預設容量 10
new ArrayList(100) // 指定初始容量
new ArrayList(collection) // 從集合複製
2. 核心增刪改查
| 方法 | 說明 | 時間複雜度 |
| add(E) | 尾部新增 | O(1) 攤還 |
| add(int, E) | 指定位置插入 | O(n) |
| get(int) | 隨機存取 | O(1) |
| set(int, E) | 替換元素 | O(1) |
| remove(int) / remove(Object) | 刪除並後移 | O(n) |
| indexOf / lastIndexOf | 線性查找 | O(n) |
| contains | 是否包含 | O(n) |
| clear | 清空 | O(n) |
3. 遍歷方式對比
List list = Arrays.asList("a", "b", "c");
// 1. for-each(最推薦,唯讀)
for (String s : list) { ... }
// 2. 索引 for(需修改或倒序刪除)
for (int i = 0; i < list.size(); i++) { ... }
// 3. Iterator(安全刪除)
Iterator it = list.iterator();
while (it.hasNext()) {
if (it.next().equals("b")) it.remove();
}
// 4. Java 8 forEach + Lambda
list.forEach(s -> System.out.println(s));
// 5. Stream 並行處理
list.parallelStream().filter(s -> s.length() > 1).collect(Collectors.toList());
4. 轉數組與互轉
// List -> 陣列
String[] arr = list.toArray(new String[0]); // 推薦寫法,JVM 優化
// 陣列 -> List(固定長度,不可增刪)
List fixed = Arrays.asList("a", "b"); // 非 ArrayList,不可 add/remove
List mutable = new ArrayList<>(Arrays.asList("a", "b")); // 可變副本
5. 擴容機制深度解析
- 預設初始容量 10,首次
add 擴容為 10。
- 擴容公式:
newCapacity = oldCapacity + (oldCapacity >> 1)(1.5 倍)。
- 擴容涉及
Arrays.copyOf,大量資料預估容量可避免多次拷貝:
// 已知約 10000 筆
List list = new ArrayList<>(10000); // 避免 10→15→22→33... 多次擴容
6. 線程安全問題與解決
| 方案 | 適用場景 | 備註 |
| Collections.synchronizedList | 低併發、簡單同步 | 迭代需手動同步 |
| CopyOnWriteArrayList | 讀多寫少、遍歷無鎖 | 寫入複製陣列,記憶體雙倍 |
| 手動 synchronized | 複雜複合操作 | 需鎖定整個列表 |
7. 效能優化清單
- 預估資料量,指定
initialCapacity。
- 頻繁查找改用
HashSet / HashMap。
- 大量刪除改用
Iterator.remove 或 removeIf(Java 8)。
- 避免在循環中
add(0, e) 導致 O(n²)。
- 序列化傳輸考慮
trimToSize() 釋放多餘容量。