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

Java 經典實作:自定義 Iterator 實作 Iterable 介面支援 for-each 遍歷

     編輯:Java 相關知識

前言

實作 Iterator 與 Iterable 介面,可讓自定義容器支援增強 for 迴圈 (for (E e : container)) 與 Java 8 forEach()。本文提供最簡完整範例,展示核心方法實現與使用方式。

完整實作程式碼


import java.util.Iterator;
import java.util.NoSuchElementException;

public class ArrayIterator implements Iterable, Iterator {
    private final T[] data;
    private int index = 0;

    public ArrayIterator(T[] data) {
        this.data = data;
    }

    public void setData(T[] data) {
        this.data = data;
        this.index = 0; // 重置迭代器
    }

    // Iterator 介面方法
    @Override
    public boolean hasNext() {
        return index < data.length;
    }

    @Override
    public T next() {
        if (hasNext()) {
            return data[index++];
        }
        throw new NoSuchElementException("只有 " + data.length + " 個元素");
    }

    @Override
    public void remove() {
        throw new UnsupportedOperationException("此示範未實作 remove");
    }

    // Iterable 介面方法:支援 for-each
    @Override
    public Iterator iterator() {
        index = 0; // 重置位置
        return this; // 本身即是 Iterator
    }

    // 測試主程式
    public static void main(String[] args) {
        String[] names = {"rose", "petunia", "tulip"};
        ArrayIterator iter = new ArrayIterator<>(names);

        // Java 5/6 風格 for-each
        for (String s : iter) {
            System.out.println(s);
        }

        // Java 8 風格 forEach
        iter.forEach(System.out::println);
    }
}

執行結果

rose
petunia
tulip
rose
petunia
tulip

核心要點解析

1. 雙重實作:Iterable + Iterator

  • Iterable:標記「可被迭代」,提供 iterator() 方法
  • Iterator:實際迭代邏輯 (hasNext/next/remove)
  • 同一類別同時實作兩介面,iterator() 回傳 this 最簡潔

2. 關鍵方法契約

方法契約異常
hasNext()是否有下一個元素無
next()回傳下一個元素並推進游標無元素拋 NoSuchElementException
remove()移除上次 next() 返回的元素未呼叫 next 先呼叫拋 IllegalStateException;不支援拋 UnsupportedOperationException
iterator()回傳新/重置的 Iterator無

3. for-each 編譯器轉換


// 原始碼
for (String s : iter) { ... }

// 編譯器轉換為
for (Iterator it = iter.iterator(); it.hasNext(); ) {
    String s = it.next();
    ...
}

4. Java 8 forEach 預設方法


// Iterable 中的 default 方法
default void forEach(Consumer action) {
    for (T t : this) action.accept(t);
}
// 直接呼叫 iter.forEach(System.out::println);

進階擴展:分離 Iterable 與 Iterator

生產級容器通常分離兩介面,避免迭代器狀態干擾:


public class MyList implements Iterable {
    private T[] data;
    // ...
    @Override
    public Iterator iterator() {
        return new MyIterator(); // 每次新建獨立迭代器
    }

    private class MyIterator implements Iterator {
        private int cursor = 0;
        // 實作 hasNext/next/remove
    }
}

常見錯誤避坑

  1. iterator() 未重置游標:第二次 for-each 直接結束
  2. next() 未檢查 hasNext:直接存取陣列導致 IndexOutOfBoundsException
  3. remove() 未實作或拋錯誤異常:需拋 UnsupportedOperationException 而非其他
  4. 泛型型別擦除導致陣列建立問題:new T[size] 不合法,需 (T[]) new Object[size] 或用 List

JDK 內建實作參考

  • ArrayList.Itr:內部類,支援快速失效 (fail-fast)
  • LinkedList.ListItr:實作 ListIterator,雙向遍歷
  • HashMap.KeyIterator:遍歷 Entry、取 Key

總結

實作 Iterable + Iterator 只需 4 個核心方法 (hasNext/next/remove/iterator),即可讓自定義類別無縫融入 Java 集合生態,支援 for-each、Stream API、forEach 等現代語法。掌握此模式是建立領域模型容器、封裝第三方資料源的關鍵技能。

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