Java 開發者每天都在用迭代器:
Iterator it = list.iterator();
while (it.hasNext()) {
String item = it.next();
// 業務邏輯
}
這正是迭代器模式的經典應用——提供統一介面順序存取聚合物件內部元素,而無需暴露其內部結構。
GoF 定義:提供一種方法訪問容器物件中各個元素,而又不需暴露該物件的內部細節。
| 角色 | 類別/介面 | 職責 |
|---|---|---|
| Iterator | 介面 | 定義 hasNext()、next()、remove() 等遍歷操作 |
| ConcreteIterator | 類別 | 實現遍歷演算法,維護當前游標位置 |
| Container (Aggregate) | 介面 | 宣告 iterator() 工廠方法 |
| ConcreteContainer | 類別 | 實現 iterator() 返回專屬迭代器實例 |
| 類型 | 控制權 | 特點 |
|---|---|---|
| 外部迭代器 | 客戶端 | 靈活、可暫停/恢復、支援多重並發遍歷,Java 採用此模式 |
| 內部迭代器 | 迭代器自身 | 簡單但剛性,難以支援嵌套/並發遍歷,Java 中較少見 |
AbstractList.Itr 為內部類實現:
private class Itr implements Iterator {
int cursor = 0; // 下一個元素索引
int lastRet = -1; // 上次返回元素索引
int expectedModCount = modCount; // 快速失效機制
public boolean hasNext() { return cursor != size(); }
public E next() {
checkForComodification();
try {
E next = get(cursor);
lastRet = cursor++;
return next;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
public void remove() {
if (lastRet == -1) throw new IllegalStateException();
checkForComodification();
try {
AbstractList.this.remove(lastRet);
if (lastRet < cursor) cursor--;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException e) {
throw new ConcurrentModificationException();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
客戶端程式碼只依賴 Iterator 介面,可透明遍歷 ArrayList、LinkedList、HashSet、TreeSet 等任意容器:
public void printAll(Collection> coll) {
for (Iterator> it = coll.iterator(); it.hasNext(); ) {
System.out.println(it.next());
}
}
| 挑戰 | 解決思路 |
|---|---|
| 遍歷過程中修改容器 | 採用快速失效:維護 modCount,檢測並發修改拋出 ConcurrentModificationException |
| 支援深度遍歷(樹/圖) | 迭代器內部維護堆疊/隊列,實現前序/中序/後序/廣度優先等多種策略 |
| 多種遍歷方式共存 | 容器提供多個工廠方法:preOrderIterator()、breadthFirstIterator() 等 |
Spliterator:可分割迭代器,支援並行遍歷,是 Stream API 底層基石stream() / parallelStream():宣告式資料處理,內部迭代器,自動並行化Iterator 仍是基礎,Stream 內部仍依賴 Spliterator/Iterator迭代器模式是容器與演算法解耦的經典範例。它將「如何遍歷」從「儲存什麼」中分離,支援多種遍歷策略並存、同一容器並發多重遍歷、統一介面屏蔽底層結構差異。理解其內部類實現、快速失效機制、多態迭代本質,有助於深入掌握 Java 集合框架與 Stream API 的設計精髓。