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

Java 迭代器模式深度解析:從介面設計到自定義集合實戰

     編輯:Java 程式設計入門

模式核心:統一遍歷介面,隱藏內部結構

迭代器模式提供一種方法順序訪問聚合對象元素,而無需暴露其內部表示。Java 集合框架完整實現了此模式。

核心介面定義

// 聚合介面
public interface Collection {
    void add(E e);
    int size();
    Iterator iterator();  // 工廠方法:創建迭代器
}

// 迭代器介面
public interface Iterator {
    boolean hasNext();  // 是否有下一個
    E next();           // 返回下一個並移動游標
    // Java 8+ 默認方法
    default void remove() { throw new UnsupportedOperationException(); }
    default void forEachRemaining(Consumer action) { ... }
}

自定義 ArrayList 實現

public class MyArrayList implements Collection {
    private static final int DEFAULT_CAPACITY = 10;
    private Object[] elements;
    private int size;
    
    public MyArrayList() {
        elements = new Object[DEFAULT_CAPACITY];
    }
    
    @Override
    public void add(E e) {
        ensureCapacity(size + 1);
        elements[size++] = e;
    }
    
    private void ensureCapacity(int minCapacity) {
        if (minCapacity > elements.length) {
            int newCapacity = elements.length + (elements.length >> 1);
            elements = Arrays.copyOf(elements, newCapacity);
        }
    }
    
    @Override
    public int size() { return size; }
    
    @Override
    public Iterator iterator() {
        return new ArrayListIterator();
    }
    
    // 內部類實現迭代器(訪問外部類私有欄位)
    private class ArrayListIterator implements Iterator {
        private int cursor = 0;           // 下一個元素索引
        private int lastRet = -1;         // 最後返回元素索引
        
        @Override
        public boolean hasNext() {
            return cursor < size;
        }
        
        @Override
        @SuppressWarnings("unchecked")
        public E next() {
            if (!hasNext()) throw new NoSuchElementException();
            lastRet = cursor;
            return (E) elements[cursor++];
        }
        
        @Override
        public void remove() {
            if (lastRet < 0) throw new IllegalStateException();
            MyArrayList.this.remove(lastRet);
            cursor = lastRet;
            lastRet = -1;
        }
    }
    
    // 內部刪除方法(供迭代器調用)
    private E remove(int index) {
        @SuppressWarnings("unchecked")
        E old = (E) elements[index];
        int numMoved = size - index - 1;
        if (numMoved > 0) System.arraycopy(elements, index + 1, elements, index, numMoved);
        elements[--size] = null;
        return old;
    }
}

測試驗證

public class IteratorPatternDemo {
    public static void main(String[] args) {
        Collection list = new MyArrayList<>();
        for (int i = 0; i < 15; i++) {
            list.add("元素" + i);
        }
        
        System.out.println("大小: " + list.size());  // 15
        
        // 多態調用:介面類型持有具體實現
        Iterator it = list.iterator();
        while (it.hasNext()) {
            String elem = it.next();
            System.out.println(elem);
            
            // 安全刪除示範
            if (elem.equals("元素5")) {
                it.remove();
                System.out.println(">>> 已刪除: " + elem);
            }
        }
        
        System.out.println("刪除後大小: " + list.size());  // 14
    }
}

JDK 內建迭代器 vs 自定義

進階:可迭代介面與增強 for

// 實現 Iterable 即可使用 for-each 循環
public class MyArrayList implements Collection, Iterable {
    // ... 
    
    @Override
    public Iterator iterator() {
        return new ArrayListIterator();
    }
}

// 使用
for (String s : list) {  // 編譯器自動調用 iterator()
    System.out.println(s);
}

實戰場景:組合模式中的迭代器

// 文件系統節點
interface FileSystemNode extends Iterable {
    String getName();
    boolean isDirectory();
}

// 文件
class FileNode implements FileSystemNode {
    private String name;
    public FileNode(String name) { this.name = name; }
    public String getName() { return name; }
    public boolean isDirectory() { return false; }
    public Iterator iterator() { 
        return Collections.emptyIterator();  // 叶子節點無子元素
    }
}

// 目錄
class DirectoryNode implements FileSystemNode {
    private String name;
    private List children = new ArrayList<>();
    public DirectoryNode(String name) { this.name = name; }
    public void add(FileSystemNode node) { children.add(node); }
    public String getName() { return name; }
    public boolean isDirectory() { return true; }
    public Iterator iterator() { return children.iterator(); }
}

// 深度優先遍歷(使用疊代器遞歸)
void printTree(FileSystemNode root, String indent) {
    System.out.println(indent + (root.isDirectory() ? "[D] " : "[F] ") + root.getName());
    if (root.isDirectory()) {
        for (FileSystemNode child : root) {  // 增強 for 自動使用 iterator()
            printTree(child, indent + "  ");
        }
    }
}

最佳實踐總結

  1. 集合實現 Iterable:支援 for-each、Stream API、工具類操作
  2. 迭代器為內部類:訪問私有欄位、封裝遍歷狀態
  3. 正確實現 remove():同步更新集合狀態、拋出 IllegalStateException(未調用 next 時)
  4. 考慮 fail-fast:非併發集合添加 modCount 機制
  5. 不可變集合返回空迭代器:Collections.emptyIterator()

總結

迭代器模式是 Java 集合框架的基石。**介面隔離變化、內部類封裝狀態、多態實現統一遍歷**是其核心精髓。理解並能手寫迭代器,是掌握集合框架源碼、設計可擴展資料結構的關鍵能力。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
特性JDK 集合迭代器自定義實現重點
fail-fastmodCount 機制檢測結構修改單線程環境可簡化或省略
fail-safeCopyOnWriteArrayList、ConcurrentHashMap複製底層數據、遍歷快照
remove()支援、更新 modCount需同步更新集合 size/陣列
forEachRemaining默認實現、可被重寫優化簡單場景用默認即可