迭代器模式:統一不同數據結構的遍歷方式

迭代器模式:統一不同數據結構的遍歷方式

一、模式核心:分離數據遍歷與數據表示

在開發中,我們經常需要遍歷不同的數據結構,如數組、鏈表、樹等。若在客戶端代碼中直接編寫遍歷邏輯,不僅會導致代碼冗余,而且當數據結構發生變化時,遍歷邏輯也需要隨之修改。迭代器模式(Iterator Pattern 通過將遍歷邏輯封裝成獨立的迭代器對象,實現數據結構與遍歷算法的解耦,核心解決:

  • 統一遍歷接口:為不同數據結構提供一致的遍歷方式,如hasNext()next()
  • 隱藏數據結構細節:客戶端無需了解數據存儲的具體結構(如鏈表的節點操作),僅通過迭代器操作數據。
  • 支持復雜遍歷:方便實現倒序遍歷、跳躍遍歷等特殊遍歷需求。

核心思想與 UML 類圖

迭代器模式主要包含迭代器接口、具體迭代器、聚合接口和具體聚合四個角色:

PlantUML Diagram

二、核心實現:自定義數組與鏈表的統一遍歷

1. 定義迭代器接口(規范遍歷操作)

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

2. 定義聚合接口(提供創建迭代器的方法)

public interface Aggregate {Iterator createIterator();
}

3. 實現具體聚合類(以數組為例)

public class ArrayAggregate implements Aggregate {private Object[] items;private int size;public ArrayAggregate(int capacity) {items = new Object[capacity];}public void addItem(Object item) {items[size++] = item;}public int size() {return size;}public Object getItem(int index) {return items[index];}@Overridepublic Iterator createIterator() {return new ArrayIterator(this);}// 具體迭代器類(內部類)private class ArrayIterator implements Iterator {private ArrayAggregate aggregate;private int index = 0;public ArrayIterator(ArrayAggregate aggregate) {this.aggregate = aggregate;}@Overridepublic boolean hasNext() {return index < aggregate.size();}@Overridepublic Object next() {return aggregate.getItem(index++);}}
}

4. 實現鏈表聚合類及對應迭代器

// 鏈表節點類
class ListNode {Object data;ListNode next;public ListNode(Object data) {this.data = data;}
}// 鏈表聚合類
public class ListAggregate implements Aggregate {private ListNode head;public void addItem(Object item) {ListNode newNode = new ListNode(item);if (head == null) {head = newNode;} else {ListNode current = head;while (current.next != null) {current = current.next;}current.next = newNode;}}@Overridepublic Iterator createIterator() {return new ListIterator(head);}// 鏈表迭代器類private class ListIterator implements Iterator {private ListNode current;public ListIterator(ListNode head) {this.current = head;}@Overridepublic boolean hasNext() {return current != null;}@Overridepublic Object next() {Object data = current.data;current = current.next;return data;}}
}

5. 客戶端調用示例

public class ClientDemo {public static void main(String[] args) {// 使用數組聚合類ArrayAggregate arrayAggregate = new ArrayAggregate(3);arrayAggregate.addItem("Apple");arrayAggregate.addItem("Banana");arrayAggregate.addItem("Cherry");Iterator arrayIterator = arrayAggregate.createIterator();while (arrayIterator.hasNext()) {System.out.println(arrayIterator.next());}// 使用鏈表聚合類ListAggregate listAggregate = new ListAggregate();listAggregate.addItem("Dog");listAggregate.addItem("Elephant");listAggregate.addItem("Fox");Iterator listIterator = listAggregate.createIterator();while (listIterator.hasNext()) {System.out.println(listIterator.next());}}
}

三、進階:實現倒序遍歷與并發安全迭代器

1. 倒序遍歷迭代器

public class ReverseArrayIterator implements Iterator {private ArrayAggregate aggregate;private int index;public ReverseArrayIterator(ArrayAggregate aggregate) {this.aggregate = aggregate;this.index = aggregate.size() - 1;}@Overridepublic boolean hasNext() {return index >= 0;}@Overridepublic Object next() {return aggregate.getItem(index--);}
}// 客戶端調用倒序遍歷
ArrayAggregate arrayAggregate = new ArrayAggregate(3);
// 添加元素...
Iterator reverseIterator = new ReverseArrayIterator(arrayAggregate);
while (reverseIterator.hasNext()) {System.out.println(reverseIterator.next());
}

2. 并發安全迭代器(使用讀寫鎖)

import java.util.concurrent.locks.ReentrantReadWriteLock;public class ThreadSafeArrayAggregate implements Aggregate {private Object[] items;private int size;private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();public ThreadSafeArrayAggregate(int capacity) {items = new Object[capacity];}public void addItem(Object item) {lock.writeLock().lock();try {items[size++] = item;} finally {lock.writeLock().unlock();}}public int size() {lock.readLock().lock();try {return size;} finally {lock.readLock().unlock();}}public Object getItem(int index) {lock.readLock().lock();try {return items[index];} finally {lock.readLock().unlock();}}@Overridepublic Iterator createIterator() {return new ThreadSafeArrayIterator(this);}private class ThreadSafeArrayIterator implements Iterator {private ThreadSafeArrayAggregate aggregate;private int index = 0;public ThreadSafeArrayIterator(ThreadSafeArrayAggregate aggregate) {this.aggregate = aggregate;}@Overridepublic boolean hasNext() {lock.readLock().lock();try {return index < aggregate.size();} finally {lock.readLock().unlock();}}@Overridepublic Object next() {lock.readLock().lock();try {return aggregate.getItem(index++);} finally {lock.readLock().unlock();}}}
}

四、框架與源碼中的迭代器實踐

1. Java 集合框架(java.util包)

  • 核心接口java.util.Iteratorjava.util.ListIterator
  • 示例:遍歷ArrayList
import java.util.ArrayList;
import java.util.Iterator;public class JavaIteratorExample {public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();list.add("A");list.add("B");Iterator<String> iterator = list.iterator();while (iterator.hasNext()) {System.out.println(iterator.next());}}
}

2. Hibernate 的迭代器(ScrollableResults

  • 用于處理大量數據查詢,避免一次性加載全部數據到內存
Session session = sessionFactory.openSession();
Query query = session.createQuery("from User");
ScrollableResults results = query.scroll();
while (results.next()) {User user = (User) results.get(0);// 處理用戶數據
}
results.close();

3. Python 中的迭代器與生成器

  • 迭代器協議:通過__iter__()__next__()方法實現
  • 生成器:使用yield關鍵字簡化迭代器實現
# 生成器函數
def fibonacci():a, b = 0, 1while True:yield aa, b = b, a + b# 使用生成器
for num in fibonacci():if num > 100:breakprint(num)

五、避坑指南:正確使用迭代器模式的 3 個要點

1. 避免在迭代過程中修改聚合對象

  • ? 反模式:在迭代器遍歷過程中刪除聚合元素(可能導致ConcurrentModificationException
  • ? 最佳實踐:使用remove()方法(若迭代器支持),或先記錄待刪除元素,遍歷結束后再操作。

2. 處理空聚合的邊界情況

  • 確保hasNext()在空聚合中返回falsenext()在空聚合或遍歷結束后拋出NoSuchElementException

3. 迭代器的生命周期管理

  • 避免迭代器被長時間持有,導致資源無法釋放(如數據庫游標未關閉)。
  • 對于一次性遍歷需求,可使用匿名內部類或局部內部類簡化代碼。

4. 反模式:過度封裝簡單遍歷

  • 對于簡單的數組或集合遍歷,直接使用for-each循環可能更簡潔,無需引入迭代器模式。

六、總結:何時該用迭代器模式?

適用場景核心特征典型案例
遍歷多種數據結構數據存儲結構復雜(如樹、圖),需統一遍歷方式文件系統目錄遍歷、數據庫查詢結果遍歷
分離數據結構與遍歷邏輯避免客戶端耦合具體數據結構實現細節集合框架、ORM 框架
支持復雜遍歷需求需要實現倒序遍歷、跳躍遍歷、并發遍歷等大數據處理、多線程迭代

迭代器模式通過 “封裝遍歷 + 解耦結構” 的設計,使數據的訪問與存儲方式分離,提升了代碼的可維護性和擴展性。下一篇我們將深入探討裝飾模式,解析如何在不修改原有類的基礎上動態添加功能,敬請期待!

擴展思考:迭代器模式 vs 枚舉(Enumeration)

模式功能特性線程安全可修改性典型應用
迭代器模式支持刪除、雙向遍歷、自定義遍歷需手動實現支持集合框架、復雜數據結構遍歷
枚舉僅支持單向遍歷,功能較簡單部分支持不支持早期 Java 集合遍歷

理解這些差異,有助于在不同場景下選擇合適的遍歷方案。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/77457.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/77457.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/77457.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Oracle 如何停止正在運行的 Job

Oracle 如何停止正在運行的 Job 先了解是dbms_job 還是 dbms_scheduler&#xff0c;再確定操作命令。 一 使用 DBMS_JOB 包停止作業&#xff08;適用于舊版 Job&#xff09; 1.1 查看正在運行的 Job SELECT job, what, this_date, this_sec, failures, broken FROM user_j…

真實波幅策略思路

該策略是一種基于ATR&#xff08;Average True Range&#xff09;指標的交易策略&#xff0c;主要用于期貨市場中的日內交易。策略的核心思想是利用ATR指標來識別市場的波動范圍&#xff0c;并結合均線過濾來確定買入和賣出的時機。 交易邏輯思維 1. 數據準備與初始化 - 集合競…

Web3技術如何提升用戶數據保護

在這個信息爆炸的時代&#xff0c;用戶數據保護已成為全球關注的焦點。Web3 技術&#xff0c;作為下一代互聯網的代表&#xff0c;以其去中心化、安全性和用戶主權等特點&#xff0c;為用戶數據保護提供了新的解決方案。本文將探討 Web3 技術如何提升用戶數據保護。 去中心化存…

銀河麒麟系統 達夢8 安裝 dlask 框架后端環境

適配的一套環境為 dmPython2.5.8 dmSQLAlchemy1.4.39 Flask2.0.3 Flask-Cors3.0.10 Flask-SQLAlchemy2.5.1 SQLAlchemy1.4.54 Werkzeug2.2.2其中 # sqlalchemy-dm1.4.39 通過dmdbms目錄內文件進行源碼安裝 (MindSpore) [ma-user python]$pwd /home/syl/dmdbms/drivers/python…

利用 i2c 快速從 Interface 生成 Class

利用 i2c 快速從 Interface 生成 Class&#xff08;支持 TS & ArkTS&#xff09; 在日常 TypeScript 或 ArkTS 開發中&#xff0c;需要根據 interface 定義手動實現對應的 class&#xff0c;這既重復又容易出錯。分享一個命令行工具 —— interface2class&#xff0c;簡稱…

015-C語言字符函數和字符串函數

C語言字符函數和字符串函數 文章目錄 C語言字符函數和字符串函數1. 字符分類函數2. 字符轉換函數3. strlen4. strcpy5. strcat6. strcmp7. strncpy8. strncat9. strncmp10. strstr11. strtok12. strerror 1. 字符分類函數 C語言中有一系列函數是專門做字符分類的&#xff0c;也…

CGAL邊折疊edge_collapse的問題

使用edge_collapse對一個模型簡化&#xff0c;之后回收垃圾&#xff0c;collect_garbage 處理之前的頂點和三角形數量&#xff1a; number_of_vertices: 955730 number_of_faces: 1903410 num_vertices: 955730 num_faces: 1903410 處理之后的頂點和三角形數量&#xff1a;…

用c語言實現——順序隊列支持用戶輸入交互、入隊、出隊、查找、遍歷、計算隊列長度等功能。確定判斷判滿的方法為:犧牲一個存儲單元方式

一、知識介紹 1.基本原理 在順序隊列中&#xff0c;我們使用一個固定大小的數組來存儲隊列中的元素&#xff0c;并使用兩個指針&#xff08;front 和 rear&#xff09;來分別表示隊頭和隊尾的位置。 隊列為空的條件&#xff1a;front rear 隊列滿的條件&#xff1a;rear 1…

JVM 系列:JVM 內存結構深度解析

你點贊了嗎&#xff1f;你關注了嗎&#xff1f;每天分享干貨好文。 高并發解決方案與架構設計。 海量數據存儲和性能優化。 通用框架/組件設計與封裝。 如何設計合適的技術架構&#xff1f; 如何成功轉型架構設計與技術管理&#xff1f; 在競爭激烈的大環境下&#xff0c…

手機上的APN是什么,該怎么設置

網上說改個APN就可以讓網速快幾倍&#xff0c;那到底APN是個什么東西&#xff0c;真的能讓網速快幾倍嗎&#xff1f; APN的作用 網絡連接基礎&#xff1a;APN&#xff08;接入點名稱&#xff09;是手機連接移動網絡的“橋梁”&#xff0c;負責識別運營商網絡類型&#xff08;…

微服務治理與可觀測性

服務注冊與發現 核心功能 服務實例動態變化&#xff1a;實例可能因擴縮容、故障或遷移導致IP變動。服務依賴解耦&#xff1a;調用方無需硬編碼服務地址&#xff0c;降低耦合度。負載均衡&#xff1a;自動選擇健康實例&#xff0c;提升系統可用性。 核心組件 服務注冊中心&am…

嵌入式linux系統中內存管理的方法與實現

第一:linux內核管理詳解圖形 第二:Linux內存管理詳細分析 深入剖析Linux內核內存管理 作為嵌入式系統開發者,理解Linux內核的內存管理對于開發高效、穩定的系統至關重要。在這篇文章中,我們將詳細解析Linux內核如何劃分物理內存和虛擬內存,頁表、MMU(內存管理單元)與TL…

【dataframe顯示不全問題】打開一個行列超多的excel轉成df之后行列顯示不全

出現問題如下圖&#xff1a; 解決方案&#xff5e; display.width解決列顯示不全 pd.set_option(display.max_columns,1000) pd.set_option(display.width, 1000) pd.set_option(display.max_colwidth,1000) pd.set_option(display.max_rows,1000)

Linux——Shell編程之正則表達式與文本處理器(筆記)

目錄 基礎正則表達式 1:基礎正則表達式示例 &#xff08;4&#xff09;查找任意一個字符“.”與重新字符“*” &#xff08;5&#xff09;查找連續字符范圍“{ }” 文本處理器 一、sed工具 二、awk工具 &#xff08;1&#xff09;按行輸出文本 &#xff08;2&#xff0…

OpenHarmony系統-源碼下載,環境搭建,編譯,燒錄,調試

獲取源碼 以OpenHarmony5.0.3為例 repo init -u https://gitee.com/openharmony/manifest -b OpenHarmony-5.0.3-Release --no-repo-verify repo sync -c repo forall -c git lfs pull搭建環境 安裝必要的工具和命令 apt-get install -y apt-utils binutils bison flex bc …

Vue3 本地打包啟動白屏解決思路!! !

“為什么我訪問 http://127.0.0.1:5501/index.html 白屏&#xff0c;刪了 index.html 再訪問 / 就又活過來了&#xff1f;” —— 你的項目與 SPA 路由的“宮斗大戲” 一、問題復現 場景 本地通過 VSCode Live Server&#xff08;或其他靜態服務器&#xff09;啟動了打包后的 V…

數字人(2):數字人技術全景透視(2025演進版)

隨著人工智能技術的迅猛發展,數字人技術發展也是一日千里。站在當下,著眼未來,我們一起在回眸透視過去的基礎上,一起共同眺望數字人技術的未來。 一、數字人技術體系重構 我們可以用三維定義對數字人技術進行框架重構 維度 技術內涵 典型特征 物理層 人體數字化建模技術 …

小剛說C語言刷題——1035 判斷成績等級

1.題目描述 輸入某學生成績&#xff0c;如果 86分以上(包括 86分&#xff09;則輸出 VERY GOOD &#xff0c;如果在 60到 85之間的則輸出 GOOD (包括 60和 85)&#xff0c;小于 60 的則輸出 BAD。 輸入 輸入只有一行&#xff0c;包括 1個整數。 輸出 輸出只有一行&#xf…

React-在使用map循環數組渲染列表時須指定唯一且穩定值的key

在渲染列表的時候&#xff0c;我們須給組件或者元素分配一個唯一值的key, key是一個特殊的屬性&#xff0c;不會最終加在元素上面&#xff0c;也無法通過props.key來獲取&#xff0c;僅在react內部使用。react中的key本質是服務于diff算法, 它的默認值是null, 在diff算法過程中…

Zookeeper的通知機制是什么?

大家好&#xff0c;我是鋒哥。今天分享關于【Zookeeper的通知機制是什么&#xff1f;】面試題。希望對大家有幫助&#xff1b; Zookeeper的通知機制是什么&#xff1f; 1000道 互聯網大廠Java工程師 精選面試題-Java資源分享網 Zookeeper 的通知機制是其核心特性之一&#xf…