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

Java 集合框架源碼深度剖析:Iterator 模式實現內幕

     編輯:Java 相關知識

Collection 根介面核心方法

java.util.Collection 為所有集合類根類型。關鍵方法語意:

  • boolean add(Object):回傳值非表示成功與否(失敗會拋例外),而是表示「集合內容是否發生變化」(元素數量/位置改變)。同理 addAll/remove/removeAll/retainAll。
  • toArray() / toArray(Object[]):後者回傳陣列型別與參數一致;參數陣列足夠大則回傳該陣列(內容填入),不足則新建陣列;若參數陣列較大,多餘位置設為 null。
  • iterator():回傳 Iterator,統一遍歷介面。

Iterator 模式動機

無 Iterator 時,客戶端必須知悉內部結構:

// 陣列用索引
for (int i=0; i<list.size(); i++) { ... list.get(i) ... }

// 鏈表用指標
while ((e = e.next()) != null) { ... e.data() ... }

耦合度高、無法復用、換集合類別需重寫遍歷邏輯。Iterator 模式統一為:

for (Iterator it = c.iterator(); it.hasNext(); ) { ... it.next() ... }

奧義在於:遍歷狀態(游標、是否有下一個)由 Iterator 維護,集合類別透過工廠方法 iterator() 產生對應的 Iterator,客戶端僅操作 Iterator 介面。

Iterator 介面定義 (JDK 1.4)

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(ArrayIterator、SetIterator 等),但皆實作 Iterator 介面,體現面向介面程式設計。

AbstractList 內部類 Itr 源碼剖析

private class Itr implements Iterator {
    int cursor = 0;           // 下一次 next() 回傳的索引
    int lastRet = -1;         // 上一次回傳的索引
    int expectedModCount = modCount; // 快照 modCount,用於檢測並發修改
}

hasNext()

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

next()

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

快速失效機制

AbstractList 持有 modCount (初始 0),每次結構性修改 (add/remove 等) 遞增。Itr 建構時快照 expectedModCount,關鍵處呼叫 checkForComodification():

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

ConcurrentModificationException 為 RuntimeException,**不可捕獲忽略**,出現即表示程式邏輯錯誤(如遍歷中修改集合),需檢查代碼。

Iterator 自身的 remove() 安全

public void remove() {
    ...
    AbstractList.this.remove(lastRet);
    ...
    expectedModCount = modCount; // 同步快照,避免誤判
    ...
}

最佳實踐原則

  • 遍歷過程**嚴禁**修改集合內容(呼叫 Iterator.remove() 除外)。
  • 單執行緒使用集合,或多執行緒時對遍歷區塊加同步。
  • 面向介面程式:Collection c = new 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);
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved