interface Iterable<T> {
Iterator<T> iterator();
}
interface Iterator<E> {
boolean hasNext();
E next();
void remove(); // 選用操作
}
Collection 實作 Iterable,故可用 for-each。iterator() 回傳**新的**迭代器實例,每次遍歷互不干擾。原始碼:
for (String s : list) { System.out.println(s); }
編譯器轉換為(JDK 8+ 簡化版):
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String s = it.next();
System.out.println(s);
}
結論:for-each **本質上就是語法糖**,底層完全依賴 Iterator。
List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));
for (String s : list) {
if ("B".equals(s)) list.remove(s); // 拋 ConcurrentModificationException
}
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String s = it.next();
if ("B".equals(s)) list.remove(s); // 同樣拋異常,必須用 it.remove()
}
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String s = it.next();
if ("B".equals(s)) it.remove(); // 唯一合法的遍歷中修改方式
}
原理:ArrayList.Itr 內部維護 expectedModCount,若偵測到 modCount != expectedModCount 即拋異常。it.remove() 會同步更新 expectedModCount。
只需實作 Iterable<T> 並回傳有效 Iterator:
class MyCollection<T> implements Iterable<T> {
private final List<T> data = new ArrayList<>();
public void add(T t) { data.add(t); }
@Override public Iterator<T> iterator() { return data.iterator(); }
}
// 使用
MyCollection<String> mc = new MyCollection<>();
mc.add("Java"); mc.add("Go");
for (String s : mc) System.out.println(s); // 正常運作
僅 List 實作提供 listIterator():
hasPrevious() / previous():反向遍歷。nextIndex() / previousIndex():取得索引。set(E):替換元素。add(E):在游標位置插入。list.stream().filter(s -> !"B".equals(s)).forEach(System.out::println);
// 或收集新列表
List<String> filtered = list.stream().filter(s -> !"B".equals(s)).collect(Collectors.toList());
優點:不可變風格、避免並發修改異常、可並行 (parallelStream())。
| 場景 | 建議 |
|---|---|
| 單純遍歷讀取 | for-each 最簡潔 |
| 遍歷中需刪除/修改 | 顯式 Iterator + remove()/set() |
| 需索引或反向遍歷 | ListIterator 或 傳統 for (int i=0; i<size; i++) |
| 複雜篩選/轉換/聚合 | Stream API |
| 高效能數值計算 | 基本型別陣列 + 傳統 for 迴圈 |
for-each 是 Iterator 的語法糖,**遍歷時修改集合必須使用迭代器自身的 remove()**,否則觸發 ConcurrentModificationException。理解底層 modCount 機制,並善用 ListIterator、Stream 等進階工具,能寫出更安全、更具表達力的集合處理程式碼。