List 是 Collection 子介面,代表有序、可重複、允許 null 的元素序列。本文系統整理 List 核心方法、三大實作類別差異、迭代器用法、並發修改異常處理與效能選型建議,附完整可執行範例程式碼。
get(index)、set(index, e)、add(index, e)| 實作類別 | 底層結構 | 查詢 | 增刪(頭/中間) | 增刪(尾部) | 線程安全 | 適用場景 |
|---|---|---|---|---|---|---|
| ArrayList | 動態陣列 | O(1) | O(N) | O(1) 攤還 | 否 | 隨機存取多、尾部增刪 |
| LinkedList | 雙向鏈表 | O(N) | O(1) | O(1) | 否 | 頻繁頭/中間增刪、佇列/棧 |
| Vector | 動態陣列 | O(1) | O(N) | O(1) | 是 (synchronized) | 舊代碼相容、極少用 |
List list = new ArrayList<>();
list.add("紅樓夢"); // 尾部新增
list.add(1, "偉大的世界"); // 指定索引插入,後續元素右移
list.addAll(Arrays.asList("西遊記", "水滸傳")); // 尾部批量新增
list.addAll(1, otherList); // 指定索引批量插入
// 索引越界拋 IndexOutOfBoundsException
// list.add(5, "錯誤"); // Size=4 時拋出異常
String first = list.get(0); // 索引取得
int idx = list.indexOf("紅樓夢"); // 首次出現索引 (0)
int lastIdx = list.lastIndexOf("紅樓夢"); // 最後出現索引 (4)
List sub = list.subList(1, 3); // 視圖 [1,3),不含索引 3
// sub 為視圖,修改 sub 會影響原 list,反之亦然
String removed = list.remove(1); // 刪除索引 1,回傳被刪元素
// 後續元素左移,索引自動更新
boolean removed2 = list.remove("水滸傳"); // 刪除首個匹配元素,回傳是否成功
list.clear(); // 清空
list.set(0, "偉大的世界"); // 替換索引 0 元素
| 方式 | 程式碼 | ArrayList | LinkedList | 備註 |
|---|---|---|---|---|
| for 迴圈 + get | for(i=0;i| ★★★★★ | ★☆☆☆☆ | ArrayList 隨機存取快 | |
| for-each | for(String s : list) | ★★★★★ | ★★★★★ | 語法糖,內部用 Iterator |
| Iterator | while(it.hasNext()) it.next() | ★★★★★ | ★★★★★ | 通用、可安全移除 |
| ListIterator | 雙向遍歷、可增刪改 | ★★★★★ | ★★★★★ | List 專用,功能最強 |
| forEach (Java 8) | list.forEach(s -> ...) | ★★★★★ | ★★★★★ | 內部迭代,可能較快 |
ListIterator it = list.listIterator();
// 正向遍歷
while (it.hasNext()) {
System.out.println(it.next());
}
// 反向遍歷 (需先正向走到底)
while (it.hasPrevious()) {
System.out.println(it.previous());
}
// 迭代器操作元素 (安全)
while (it.hasNext()) {
String s = it.next();
if ("三國演義".equals(s)) {
it.add("西遊記"); // 在當前位置前插入
it.set("新三國演義"); // 替換剛讀取的元素
}
}
// it.remove() 刪除上次 next()/previous() 返回的元素
List list = new ArrayList<>(Arrays.asList("A", "B", "C"));
for (String s : list) { // 隱式使用 Iterator
if ("B".equals(s)) {
list.add("D"); // ConcurrentModificationException!
}
}
Iterator it = list.iterator();
while (it.hasNext()) {
String s = it.next();
if ("B".equals(s)) {
it.remove(); // 或 it.add("D") - 需 ListIterator
}
}
for (int i = 0; i < list.size(); i++) {
if ("B".equals(list.get(i))) {
list.add(i + 1, "D"); // 索引控制精確
i++; // 跳過新增元素
}
}
List toRemove = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
if ("B".equals(list.get(i))) toRemove.add(i);
}
for (int i = toRemove.size() - 1; i >= 0; i--) {
list.remove(toRemove.get(i).intValue()); // 從後往前刪,索引不變
}
public class ListDemo {
public static void main(String[] args) {
List books = new ArrayList<>();
// Create
books.add("紅樓夢");
books.add("三國演義");
books.add("三國演義"); // 可重複
books.add(null); // 允許 null
System.out.println("初始:" + books);
// Read
System.out.println("索引 0:" + books.get(0));
System.out.println("首現 '三國演義':" + books.indexOf("三國演義"));
System.out.println("末現 '三國演義':" + books.lastIndexOf("三國演義"));
System.out.println("子列表 [1,3):" + books.subList(1, 3));
// Update
books.set(0, "偉大的世界");
System.out.println("修改後:" + books);
// Delete
String removed = books.remove(1);
System.out.println("刪除索引 1:" + removed + ",剩餘:" + books);
// 遍歷
System.out.println("--- for-each ---");
for (String b : books) System.out.println(b);
System.out.println("--- ListIterator 反向 ---");
ListIterator it = books.listIterator(books.size());
while (it.hasPrevious()) System.out.println(it.previous());
}
}
初始:[紅樓夢, 三國演義, 三國演義, null] 索引 0:紅樓夢 首現 '三國演義':1 末現 '三國演義':2 子列表 [1,3):[三國演義, 三國演義] 修改後:[偉大的世界, 三國演義, 三國演義, null] 刪除索引 1:三國演義,剩餘:[偉大的世界, 三國演義, null] --- for-each --- 偉大的世界 三國演義 null --- ListIterator 反向 --- null 三國演義 偉大的世界
Collections.synchronizedList() 或 CopyOnWriteArrayList (讀多寫少)List.of() (Java 9+) 不可變列表List 是 Java 集合框架使用率最高的介面。掌握 ArrayList vs LinkedList 底層差異、索引操作語意、迭代器安全模式、並發修改異常三大解法,能解決 99% 實際開發中的列表操作問題。