本文詳細解析 Java 集合框架中兩大遍歷介面 Iterator 與 Enumeration 的定義、實現方式、使用場景與核心差異,助你選擇最適合的遍歷方式。
public interface Iterator<E> {
boolean hasNext(); // 是否有下一個元素
E next(); // 返回下一個元素
void remove(); // 可選:移除最後返回的元素
}
public interface Iterable<T> {
Iterator<T> iterator(); // 返回新的迭代器
}
public class Stack<Item> implements Iterable<Item> {
private Node<Item> first;
@Override
public Iterator<Item> iterator() {
return new ListIterator(first);
}
private class ListIterator<Item> implements Iterator<Item> {
private Node<Item> current;
public ListIterator(Node<Item> first) {
current = first;
}
@Override
public boolean hasNext() {
return current != null;
}
@Override
public Item next() {
if (!hasNext()) throw new NoSuchElementException();
Item item = current.item;
current = current.next;
return item;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
private static class Node<Item> {
Item item;
Node<Item> next;
}
}
// 方式一:for-each 循環 (隱式使用 Iterator)
for (String s : stack) {
System.out.println(s);
}
// 方式二:顯式使用 Iterator
Iterator<String> it = stack.iterator();
while (it.hasNext()) {
String s = it.next();
System.out.println(s);
}
public interface Enumeration<E> {
boolean hasMoreElements(); // 是否有更多元素
E nextElement(); // 返回下一個元素
}
Vector - elements() 方法返回 EnumerationHashtable - keys()、elements() 返回 EnumerationProperties - 繼承 HashtableStringTokenizer、ZipFile 等)// 獲取請求參數名稱 Enumeration
Enumeration<String> paramNames = request.getParameterNames();
while (paramNames.hasMoreElements()) {
String paramName = paramNames.nextElement();
if ("LastPage".equals(paramName.trim())) {
System.out.println("LastPage");
} else if ("NextPage".equals(paramName.trim())) {
System.out.println("NextPage");
}
}
| 維度 | Iterator | Enumeration |
|---|---|---|
| 引入版本 | JDK 1.2 (Collections Framework) | JDK 1.0 (舊版集合類) |
| 方法數量 | 3 個 (hasNext, next, remove) | 2 個 (hasMoreElements, nextElement) |
| 移除支援 | ✅ 支援 remove() 安全移除 |
❌ 僅支援遍歷,不可修改集合 |
| Fail-fast 機制 | ✅ 支援 (ArrayList, HashMap 等) | ❌ 不支援 (Vector, Hashtable 內部同步) |
| 適用集合 | 所有現代集合 (List, Set, Map.keySet() 等) | 僅 Vector、Hashtable 等舊版集合 |
| 命名風格 | 簡潔現代 (hasNext, next) | 冗長舊式 (hasMoreElements, nextElement) |
| 泛型支援 | 原生支援 | JDK 5+ 才加入泛型 |
當多執行緒同時修改集合結構 (新增/刪除元素) 時,Iterator 會檢測到 modCount 變化,立即拋出 ConcurrentModificationException,而非產生不可預期的行為。
// ArrayList Iterator 內部實現片段
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
public E next() {
checkForComodification(); // 每次 next() 都檢查
// ...
}
synchronized,單執行緒安全remove() 安全刪除當前元素HttpServletRequest.getParameterNames())Collections.list(enumeration) 轉為 List 後使用 IteratorCopyOnWriteArrayList - 迭代器不支援 remove,但絕不拋出 CMEConcurrentHashMap - 弱一致性迭代器,不拋出 CMEIterator 是現代 Java 集合遍歷的標準介面,功能更強、介面更清晰、支援 fail-fast 安全機制;Enumeration 是 JDK 1.0 遺留產物,僅用於 Vector/Hashtable 等舊版集合與部分舊版 API。新代碼應一律使用 Iterator 或 for-each 循環。