首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java 迭代器完全指南:Iterator 與 ListIterator 核心用法詳解

     編輯:Java 綜合教學

Java 迭代器完全指南:Iterator 與 ListIterator 核心用法詳解

迭代器模式是行為型設計模式之一,提供統一介面順序訪問聚合物件元素,且無需暴露內部結構。Java 集合框架通過 Iterable 介面支援迭代器,本文詳細解析 Iterator 與 ListIterator 的核心方法、使用場景與最佳實踐。

迭代器核心概念

  • 輕量級物件:創建開銷小,專注於遍歷邏輯
  • 單向遍歷:標準 Iterator 僅支援單向移動
  • 失效快速:遍歷過程中集合結構修改會拋出 ConcurrentModificationException
  • 介面定義:java.util.Iterator<E> 繼承自 Iterable<E>

Iterator 核心方法

方法說明異常
boolean hasNext()判斷是否還有下一個元素-
E next()返回下一個元素,游標後移NoSuchElementException
void remove()移除最後一次 next() 返回的元素IllegalStateException(未調用 next 或重複調用)
default void forEachRemaining(Consumer<? super E> action)Java 8+:對剩餘元素執行動作-

ListIterator 進階功能

ListIterator<E> 繼承 Iterator<E>,專為 List 設計,支援雙向遍歷與元素修改:

方法說明
boolean hasPrevious()是否有前一個元素
E previous()返回前一個元素,游標前移
int nextIndex()下一個元素索引
int previousIndex()前一個元素索引
void set(E e)替換最後訪問的元素
void add(E e)在游標位置插入元素

實戰代碼範例

基本遍歷:for 循環風格(推薦)

List<String> list = new ArrayList<>();
list.add("AA");
list.add("BB");
list.add("CC");

// 風格 1:for 循環(最常用,作用域清晰)
for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) {
    String str = iter.next();
    System.out.println(str);
}

// 風格 2:while 循環
Iterator<String> iter = list.iterator();
while (iter.hasNext()) {
    String str = iter.next();
    System.out.println(str);
}

// 風格 3:Java 8+ forEachRemaining
list.iterator().forEachRemaining(System.out::println);

安全移除元素

List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C", "B", "D"));
Iterator<String> iter = list.iterator();
while (iter.hasNext()) {
    String s = iter.next();
    if ("B".equals(s)) {
        iter.remove(); // 唯一安全的移除方式
    }
}
// 結果:[A, C, D]

ListIterator 雙向遍歷與修改

List<String> list = new LinkedList<>(Arrays.asList("A", "B", "C"));
ListIterator<String> iter = list.listIterator();

// 正向遍歷並修改
while (iter.hasNext()) {
    String s = iter.next();
    if ("B".equals(s)) {
        iter.set("B_UPDATED"); // 替換
        iter.add("INSERTED");  // 在 C 前插入
    }
}
// 當前游標在 "C" 後,可反向遍歷
while (iter.hasPrevious()) {
    System.out.print(iter.previous() + " "); // 輸出:C INSERTED B_UPDATED A
}

常見陷阱與最佳實踐

❌ 錯誤:for-each 循環中移除元素

// 編譯通過,運行拋 ConcurrentModificationException
for (String s : list) {
    if ("B".equals(s)) list.remove(s); // 禁止!
}

✅ 正確:使用 Iterator.remove()

Iterator<String> iter = list.iterator();
while (iter.hasNext()) {
    if ("B".equals(iter.next())) iter.remove();
}

✅ 正確:Java 8+ Stream 過濾(創建新集合)

List<String> filtered = list.stream()
    .filter(s -> !"B".equals(s))
    .collect(Collectors.toList());

✅ 正確:List.removeIf()(就地修改,Java 8+)

list.removeIf(s -> "B".equals(s)); // 內部使用 Iterator,線程不安全但單線程高效

自定義迭代器實現

public class CustomRange implements Iterable<Integer> {
    private final int start, end, step;
    
    public CustomRange(int start, int end, int step) {
        this.start = start; this.end = end; this.step = step;
    }
    
    @Override
    public Iterator<Integer> iterator() {
        return new Iterator<Integer>() {
            int current = start;
            @Override
            public boolean hasNext() { return current < end; }
            @Override
            public Integer next() {
                if (!hasNext()) throw new NoSuchElementException();
                int val = current;
                current += step;
                return val;
            }
        };
    }
}

// 使用:支援 for-each 循環
for (int i : new CustomRange(0, 10, 2)) {
    System.out.println(i); // 0, 2, 4, 6, 8
}

原理深度解析

ArrayList 迭代器實現

  • 內部類 Itr 實現 Iterator
  • 維護 cursor(下一個元素索引)、lastRet(最後返回索引)、expectedModCount(預期修改計數)
  • next() 檢查 modCount == expectedModCount,不一致拋出 ConcurrentModificationException

ConcurrentModificationException 觸發條件

  • 多線程並發修改同一集合
  • 單線程中:遍歷過程中直接調用集合的 add/remove/clear 方法
  • 同一迭代器多次調用 remove() 未中間調用 next()

效能比較

場景推薦方式時間複雜度
單純遍歷for-each / IteratorO(n)
遍歷中移除Iterator.remove() / removeIf()O(n)
需索引訪問for (int i=0; i<size; i++)O(1) 隨機訪問
雙向遍歷/插入ListIteratorO(1) 插入(LinkedList)
並發環境CopyOnWriteArrayList / ConcurrentLinkedQueue視實現而定

總結

  • Iterator 是集合遍歷的統一抽象,核心三方法:hasNext()、next()、remove()
  • ListIterator 增加雙向遍歷、索引獲取、元素替換與插入能力
  • 遍歷時修改集合必須使用迭代器的 remove(),或 Java 8+ removeIf()/Stream
  • 實現 Iterable 介面即可支援 for-each 循環,擴展性極強
  • 理解失效快速機制,避免並發修改異常

熟練掌握迭代器用法,是高效操作 Java 集合、編寫健壯代碼的基礎技能之一。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved