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

深入剖析 Java 集合框架中的迭代器模式實現原理

     編輯:J2EE

前言:為什麼需要 Iterator?

在沒有統一遍歷介面之前,陣列用 for (int i=0; i<size; i++),鏈表用 while ((e=e.next())!=null)。客戶端代碼與具體集合內部結構強耦合,一旦將 ArrayList 換成 LinkedList,遍歷邏輯就得全改寫。Iterator 模式正是為了解決這個問題而生:以統一介面隱藏內部結構,實現遍歷邏輯與集合實現的解耦。

Collection 根介面的關鍵契約

  • boolean add(E e):回傳值非表示成功與否,而是「集合內容是否發生變化」;失敗必須拋出異常。
  • iterator():工廠方法,回傳專屬的 Iterator 實例,啟動統一遍歷流程。

Iterator 介面定義 (JDK 1.4.2)

public interface Iterator {
    boolean hasNext();
    Object next();
    void remove();
}

標準遍歷慣用語:

for (Iterator it = c.iterator(); it.hasNext(); ) {
    Object o = it.next();
    // 處理 o
}

JDK 1.5 引入增強 for 循環 for (Type t : c),編譯器自動轉換為上述 Iterator 代碼。

AbstractList 內部類 Itr 源碼深度解析

AbstractList 以 private class Itr implements Iterator 實現迭代器,iterator() 僅回傳 new Itr()。客戶端完全不知具體類型,完美體現「面向介面編程」。

三大核心欄位

  • int cursor = 0:下一次 next() 將回傳的元素索引。
  • int lastRet = -1:上一次回傳元素的索引,供 remove() 使用。
  • int expectedModCount = modCount:快照式記錄集合修改次數,用於檢測並發修改。

關鍵方法實現

public boolean hasNext() {
    return cursor != size();
}

public Object next() {
    checkForComodification();
    try {
        Object next = get(cursor);
        lastRet = cursor++;
        return next;
    } catch (IndexOutOfBoundsException e) {
        checkForComodification();
        throw new NoSuchElementException();
    }
}

final void checkForComodification() {
    if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
}

安全移除機制

僅允許透過 Iterator 自身的 remove() 刪除當前元素,內部會同步更新 expectedModCount = modCount,避免拋出 ConcurrentModificationException。此異常屬 RuntimeException,絕不可捕捉忽略,出現即表示程式邏輯有誤,需修正代碼而非吞掉異常。

多執行緒下的遍歷安全原則

  1. 單執行緒環境:遍歷期間勿修改集合(Iterator.remove() 除外)。
  2. 多執行緒環境:對遍歷代碼塊加鎖同步,或使用 CopyOnWriteArrayList 等並發安全容器。

完整範例:一體適用於 ArrayList/LinkedList/Vector

Collection c = new ArrayList();
c.add("abc");
c.add("xyz");
for (Iterator it = c.iterator(); it.hasNext(); ) {
    String s = (String) it.next();
    System.out.println(s);
}

將第一行換成 new LinkedList() 或 new Vector(),其餘代碼完全不用動,功能不變——這就是「依賴抽象不依賴具體」的威力。

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