Java進階篇--迭代器模式

目錄

同步迭代器(Synchronous Iterator):

Iterator?接口

常用方法:

注意:

擴展小知識:

異步迭代器(Asynchronous Iterator):

常用的方法

注意:

總結:

代碼示例

示例一:

示例二:

示例三:


在Java中,可以根據迭代器的行為模式將其分為同步迭代器(Synchronous Iterator)和異步迭代器(Asynchronous Iterator)。它們是兩種不同的迭代器模式,用于在遍歷集合或序列時提供不同的行為方式。

同步迭代器(Synchronous Iterator):

同步迭代器是一種阻塞式的迭代器,它在處理當前元素時會等待操作完成后再返回下一個元素。在使用同步迭代器進行遍歷時,每次調用next()方法,迭代器會檢查當前元素是否已完成處理。如果當前元素仍在處理中,迭代器將阻塞等待,直到操作完成并返回下一個元素。

同步迭代器的優點是可以保證遍歷順序的正確性,因為每次只返回一個元素,并且等待前一個元素處理完成后才返回下一個元素。這在單線程環境或需要確保遍歷順序的場景中非常有用。Java標準庫中的?Iterator?接口就是一種同步迭代器。

Iterator?接口

在程序開發中,經常需要遍歷集合中的所有元素。針對這種需求,Java專門提供了一個接口Iterator。Iterator接口也是集合中的一員,但它與Collection、Map接口有所不同。Collection接口與Map接口主要用于存儲元素,而Iterator主要用于迭代訪問(即遍歷)Collection中的元素,因此Iterator對象也被稱為迭代器。

Iterator迭代器對象在遍歷集合時,內部采用指針的方式來跟蹤集合中的元素,為了讓初學者能更好地理解迭代器的工作原理,接下來通過一個圖例演示Iterator對象迭代元素的過程。

上圖中,在調用Iterator的next()方法之前,迭代器的索引位于第一個元素之前,不指向任何元素,當第一次調用迭代器的next()方法后,迭代器的索引會向后移動一位,指向第一個元素并將該元素返回,當再次調用next()方法時,迭代器的索引會指向第二個元素并將該元素返回,以此類推,直到hasNext()方法返回false,表示到達了集合的末尾,終止對元素的遍歷。

常用方法:

  1. boolean hasNext(): 判斷集合中是否還有下一個元素,如果有則返回true,否則返回false。
  2. E next(): 返回迭代器中的下一個元素,并將迭代器的指針向后移動一位。如果沒有下一個元素,則拋出NoSuchElementException異常。
  3. void remove(): 從集合中刪除迭代器最后一次返回的元素。注意,該方法只能在調用next方法之后且尚未再次調用remove方法時才能調用。如果在調用remove方法之前沒有調用過next方法,或者在上一次調用next方法之后又調用了remove方法,則會拋出IllegalStateException異常。

Iterator接口提供了基本的遍歷功能,可以通過循環結構配合使用hasNext和next方法來遍歷集合中的元素。同時,可以使用remove方法在遍歷過程中刪除特定元素。

注意:

  1. 通過迭代器獲取ArrayList集合中的元素時,這些元素的類型都是Object類型,如果想獲取到特定類型的元素,則需要進行對數據類型強制轉換。
  2. 在使用Iterator迭代集合時,避免直接在迭代期間修改集合結構,以免觸發ConcurrentModificationException異常。

擴展小知識:

ConcurrentModificationException異常表示在迭代器運行期間,通過集合對象對集合進行了結構性修改(如添加或刪除元素),導致迭代器的預期迭代次數與實際迭代次數不一致,從而拋出異常。

這個異常通常發生在使用普通的Iterator進行迭代時,而不是使用并發安全的迭代器(如ConcurrentHashMap的迭代器)。當你使用普通的Iterator進行迭代時,是不能在迭代過程中直接對集合進行結構性修改的,否則就會觸發ConcurrentModificationException異常。

解決此異常的方法有兩種:

  1. 使用Iterator的remove()方法:可以在迭代過程中調用Iterator的remove()方法來刪除元素,它是唯一能夠在迭代期間安全刪除元素的方法。示例代碼如下:
    Iterator<String> iterator = list.iterator();
    while (iterator.hasNext()) {String element = iterator.next();if (condition to remove element) {iterator.remove(); // 刪除當前元素,不會拋出異常}
    }
    
  2. 使用并發安全的集合類:如果需要在迭代期間對集合進行修改操作,可以考慮使用并發安全的集合類,如CopyOnWriteArrayList、ConcurrentHashMap等。這些集合類提供了迭代器的安全性,并且允許在迭代期間進行修改操作。

所以,在使用Iterator迭代集合時,避免直接在迭代期間修改集合結構,以免觸發ConcurrentModificationException異常。如果需要修改集合,請使用Iterator的remove()方法或并發安全的集合類來確保迭代器的正確性。

異步迭代器(Asynchronous Iterator):

異步迭代器是一種非阻塞式的迭代器,它在處理當前元素時不會等待操作完成而立即返回下一個元素。異步迭代器通常采用回調函數、事件通知或其他機制來進行處理結果的通知。

在使用異步迭代器進行遍歷時,調用next()方法會立即返回下一個元素,并且可能會觸發異步處理操作。迭代器會在后臺或其他線程中進行元素的處理,當處理完成時,通過回調函數或事件通知機制將結果通知給使用者。

異步迭代器的優點是可以提高遍歷效率和并發性能,因為它不需要等待當前元素的處理完成。這在多線程環境、異步編程或需要處理耗時操作的場景中非常有用。

常用的方法

  1. next(): 獲取異步迭代器的下一個元素。此方法會返回一個CompletableFuture對象,我們可以通過該對象來獲取異步操作的結果。
  2. hasNext(): 判斷異步迭代器是否還有下一個元素。返回一個CompletableFuture<Boolean>對象,用于表示是否存在下一個元素。
  3. forEachRemaining(action): 對剩余的元素執行給定的操作,直到所有元素都已處理完畢或遇到異常。
  4. tryAdvance(action): 嘗試對下一個元素執行給定的操作。如果存在下一個元素,則對其執行操作并返回true,否則返回false。
  5. close(): 關閉異步迭代器,釋放相關資源。在使用完異步迭代器后,應該及時調用該方法以避免資源泄露。

注意:

同步迭代器和異步迭代器的選擇要根據具體的需求和場景來決定。同步迭代器適合保證遍歷順序和單線程環境,而異步迭代器適合提高遍歷效率和并發性能,但可能需要額外的異步處理機制。

總結:

同步迭代器是阻塞式的,等待當前元素處理完成后再返回下一個元素;異步迭代器是非阻塞式的,在處理當前元素時不等待操作完成而立即返回下一個元素,并通過回調或事件通知機制進行結果通知。在Java中,常見的迭代器是同步迭代器,但可以根據需要自定義或使用第三方庫實現異步迭代器的功能。

代碼示例

示例一:

同步迭代器代碼示例(使用Iterator接口):

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;public class Main {public static void main(String[] args) {// 創建一個空的列表List<String> list = new ArrayList<>();// 添加元素到列表list.add("Apple");list.add("Banana");list.add("Orange");// 獲取集合的迭代器Iterator<String> iterator = list.iterator();// 循環遍歷集合中的元素while (iterator.hasNext()) {// 獲取下一個元素并移動迭代器指針String element = iterator.next();System.out.println(element);}}
}

示例二:

異步迭代器代碼示例:

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;// 自定義異步迭代器接口
interface AsyncIterator<T> {CompletableFuture<Boolean> hasNext(); // 異步判斷是否存在下一個元素CompletableFuture<T> next(); // 異步獲取下一個元素void close(); // 關閉迭代器,釋放資源
}// 異步迭代器實現類
class SimpleAsyncIterator<T> implements AsyncIterator<T> {private final T[] elements; // 數據序列private int currentIndex; // 當前索引public SimpleAsyncIterator(T[] elements) {this.elements = elements;this.currentIndex = 0;}@Overridepublic CompletableFuture<Boolean> hasNext() {return CompletableFuture.completedFuture(currentIndex < elements.length); // 完成時返回是否還有下一個元素的結果}@Overridepublic CompletableFuture<T> next() {T element = elements[currentIndex]; // 獲取當前元素currentIndex++; // 索引自增return CompletableFuture.completedFuture(element); // 完成時返回當前元素}@Overridepublic void close() {// 可以在此釋放相關資源}
}public class Main {public static void main(String[] args) {// 創建數據序列Integer[] numbers = {1, 2, 3, 4, 5};// 創建異步迭代器AsyncIterator<Integer> iterator = new SimpleAsyncIterator<>(numbers);// 創建線程池Executor executor = Executors.newFixedThreadPool(2);// 異步遍歷和處理數據序列CompletableFuture.runAsync(() -> {while (true) {CompletableFuture<Boolean> hasNextFuture = iterator.hasNext();// 異步獲取是否存在下一個元素hasNextFuture.thenCompose(hasNext -> {if (hasNext) {// 異步獲取下一個元素并處理CompletableFuture<Integer> nextFuture = iterator.next();nextFuture.thenAcceptAsync(Main::processData, executor);} else {// 處理完所有元素后關閉迭代器iterator.close();}return CompletableFuture.completedFuture(null);}).join(); // 阻塞等待完成}}, executor);}// 數據處理方法示例private static void processData(Integer data) {System.out.println("正在處理數據: " + data);// 具體的數據處理邏輯}
}

示例三:

綜合同步迭代器和異步迭代器代碼示例:

import java.util.Iterator;
import java.util.NoSuchElementException;// 同步迭代器
class SynchronousIterator implements Iterator<Integer> {private int[] array;    // 存儲數據的數組private int index;      // 當前迭代位置public SynchronousIterator(int[] array) {this.array = array;this.index = 0;}// 檢查是否還有下一個元素@Overridepublic boolean hasNext() {return index < array.length;    // 當前位置是否小于數組長度}// 返回下一個元素,并將迭代器指針向后移動一位@Overridepublic Integer next() {if (hasNext()) {                // 如果還有下一個元素int element = array[index]; // 獲取當前位置的元素index++;                    // 將迭代器指針向后移動一位return element;             // 返回當前元素}throw new NoSuchElementException();   // 拋出異常表示沒有下一個元素}
}// 異步迭代器
class AsynchronousIterator implements Iterator<Integer> {private int[] array;    // 存儲數據的數組private int index;      // 當前迭代位置public AsynchronousIterator(int[] array) {this.array = array;this.index = 0;}// 檢查是否還有下一個元素@Overridepublic boolean hasNext() {// 在此處可以進行異步操作,例如請求遠程數據或執行耗時任務// 返回 true 表示還有元素,返回 false 表示迭代結束return index < array.length;    // 當前位置是否小于數組長度}// 返回下一個元素,并將迭代器指針向后移動一位@Overridepublic Integer next() {if (hasNext()) {                // 如果還有下一個元素int element = array[index]; // 獲取當前位置的元素index++;                    // 將迭代器指針向后移動一位return element;             // 返回當前元素}throw new NoSuchElementException();   // 拋出異常表示沒有下一個元素}
}// 示例用法
public class Main {public static void main(String[] args) {int[] numbers = { 1, 2, 3, 4, 5 };   // 定義一個整數數組作為數據源// 同步迭代器示例Iterator<Integer> syncIterator = new SynchronousIterator(numbers);while (syncIterator.hasNext()) {         // 遍歷迭代器中的元素Integer number = syncIterator.next(); // 獲取當前元素System.out.println(number);           // 輸出當前元素}// 異步迭代器示例Iterator<Integer> asyncIterator = new AsynchronousIterator(numbers);while (asyncIterator.hasNext()) {         // 遍歷迭代器中的元素Integer number = asyncIterator.next(); // 獲取當前元素System.out.println(number);            // 輸出當前元素}}
}

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

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

相關文章

LeetCode 每日一題 2023/8/14-2023/8/20

記錄了初步解題思路 以及本地實現代碼&#xff1b;并不一定為最優 也希望大家能一起探討 一起進步 目錄 8/14 617. 合并二叉樹8/15 833. 字符串中的查找與替換8/16 2682. 找出轉圈游戲輸家8/17 1444. 切披薩的方案數8/18 1388. 3n 塊披薩8/19 2235. 兩整數相加8/20 8/14 617. 合…

【學習FreeRTOS】第9章——FreeRTOS任務調度

1.開啟任務調度器 vTaskStartScheduler() 作用&#xff1a;用于啟動任務調度器&#xff0c;任務調度器啟動后&#xff0c; FreeRTOS 便會開始進行任務調度【動態創建任務為例】 創建空閑任務如果使能軟件定時器&#xff0c;則創建定時器任務關閉中斷&#xff0c;防止調度器開…

Microsoft ISA服務器配置及日志分析

Microsoft ISA 分析器工具&#xff0c;可分析 Microsoft ISA 服務器&#xff08;或 Forefront 威脅管理網關服務器&#xff09;的日志并生成安全和流量報告。支持來自 Microsoft ISA 服務器組件的以下日志&#xff1a; 數據包過濾器ISA 服務器防火墻服務ISA 服務器網絡代理服務…

透過源碼理解Flutter中widget、state和element的關系

1、framework源碼組成 Flutter中widget、state、element的源碼位于framework.dart中&#xff0c;整個文件6693行(版本Flutter 3.12.0-14.0.pre.28)。整個代碼可劃分為若干部分&#xff0c;主要包括key、widget、state、element四部分。 1.1 key 關于key的代碼65行到272行&am…

NVIDIA GPU驅動和CUDA工具包 Linux CentOS 7 在線安裝指南

挑選指定系統和對應的GPU型號下載驅動和CUDA工具包: Linux CentOS安裝NVIDIA GPU驅動程序和NVIDIA CUDA工具包_centos安裝顯卡驅動和cuda_Entropy-Go的博客-CSDN博客 相比之下&#xff0c;本文是在線安裝NVIDIA GPU驅動和CUDA工具包方式&#xff0c;省去挑選對應正確安裝包的煩…

Uniapp Syntax Error: Error: Unbalanced delimiter found in string

報錯 in ./src/pages/user/components/tasks.vue?vue&typescript&langjs&Syntax Error: Error: Unbalanced delimiter found in string...這邊導致文件的原因&#xff1a;可能是條件編譯語法不小心刪了某個字符&#xff0c;導致不全&#xff0c;無法形成一對。 //…

GuLi商城-前端基礎Vue-生命周期和鉤子函數

下圖展示了實例的生命周期。你不需要立馬弄明白所有的東西&#xff0c;不過隨著你的不斷學習和使用&#xff0c;它 的參考價值會越來越高。 VUE 的生命周期指的是組件在創建、運行和銷毀過程中所經歷的一系列事件&#xff0c;通過這些事件可以 讓開發者在不同階段進行相應的…

vue3 + antv/x6 實現拖拽側邊欄節點到畫布

前篇&#xff1a;vue3ts使用antv/x6 自定義節點 前篇&#xff1a;vue3antv x6自定義節點樣式 1、創建側邊欄 用antd的menu來做側邊欄 npm i --save ant-design-vue4.x//入口文件main.js內 import Antd from ant-design-vue; import App from ./App; import ant-design-vue/…

安卓的代碼加固和其他安全問題

文章目錄 安卓加固apk文件結構dex加固過程 其它安全問題 安卓加固 從App的加固技術來看:主流分為dex加密和so加密,目前來看保護dex文件更為重要,因為dex反編譯后的java代碼可讀性更強。 android-ndk: Native Development Kit 官網解釋&#xff1a;這套工具使您能在 Android 應…

Kvm配置ovs網橋

環境&#xff1a;部署在kvm虛擬環境上&#xff08;讓虛擬機和宿主機都可以直接從路由器獲取到獨立ip&#xff09; 1、安裝ovs軟件安裝包并啟動服務&#xff08;一般采用源碼安裝&#xff0c;此處用yum安裝&#xff09; yum install openvswitch-2.9.0-3.el7.x86_64.rpm syste…

Git常見操作

一、全局配置命令 配置級別&#xff1a; –local&#xff08;默認&#xff0c;高級優先&#xff09;&#xff1a;只影響本地倉庫 –global(中優先級)&#xff1a;只影響所有當前用戶的git倉庫 –system&#xff08;低優先級&#xff09;&#xff1a;影響到全系統的git倉庫 1…

【力扣】739. 每日溫度 <單調棧>

【力扣】739. 每日溫度 給定一個整數數組 temperatures &#xff0c;表示每天的溫度&#xff0c;返回一個數組 answer &#xff0c;其中 answer[i] 是指對于第 i 天&#xff0c;下一個更高溫度出現在幾天后。如果氣溫在這之后都不會升高&#xff0c;請在該位置用 0 來代替。 …

劍指 Offer 40. 最小的k個數(C+實現)

劍指 Offer 40. 最小的k個數https://leetcode.cn/problems/zui-xiao-de-kge-shu-lcof/ 法1&#xff1a;二叉堆 通過最小堆&#xff0c;直接篩選出最小的k個數 vector<int> getLeastNumbers(vector<int>& arr, int k) {priority_queue<int, vector<int>…

YOLOv8改進后效果

數據集 自建鐵路障礙數據集-包含路障&#xff0c;人等少數標簽。其中百分之八十作為訓練集&#xff0c;百分之二十作為測試集 第一次部署 版本&#xff1a;YOLOv5 訓練50epoch后精度可達0.94 mAP可達0.95.此時未包含任何改進操作 第二次部署 版本&#xff1a;YOLOv8改進版本 首…

WebRTC | ICE詳解

目錄 一、Candidate種類與優先級 二、ICE策略 1. iceServers 2. iceTransportPolicy 三、P2P連接 1.Nat類型 &#xff08;1&#xff09;完全錐型NAT &#xff08;2&#xff09;IP限制錐型NAT &#xff08;3&#xff09;端口限制錐型NAT &#xff08;4&#xff09;對稱…

iPhone 15受益:驍龍8 Gen 3可能缺席部分安卓旗艦機

明年一批領先的安卓手機的性能可能與今年的機型非常相似。硅成本的上漲可能是原因。 你可以想象&#xff0c;2024年許多最好的手機都會在Snapdragon 8 Gen 3上運行&#xff0c;這是高通公司針對移動設備的頂級芯片系統的更新&#xff0c;尚未宣布。然而&#xff0c;來自中國的…

centos上下載redis

1.redis 特點 Redis特性&#xff08;8個&#xff09; 1 速度快&#xff1a;10w ops&#xff08;每秒10w讀寫&#xff09;&#xff0c;數據存在內存中&#xff0c;c語言實現&#xff0c;單線程模型 2 持久化&#xff1a;rdb和aof 3 多種數據結構&#xff1a; 5大數據結構 …

Vue中實現分頁

1.構造分頁組件&#xff0c;并注冊為全局組件 <template><div class"pagination"><button v-if"startNumAndEndNum.start>1" click"$emit(getPageNo,pageNo-1)">上一頁</button><button v-if"startNumAndEn…

C#生產流程控制(串行,并行混合執行)

開源框架CsGo https://gitee.com/hamasm/CsGo?_fromgitee_search 文檔資料&#xff1a; https://blog.csdn.net/aa2528877987/article/details/132139337 實現效果 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37…

Windows11 Docker Desktop 啟動 -wsl kernel version too low

系統環境&#xff1a;windows11 1&#xff1a;docker下載 Docker: Accelerated Container Application Development 下載后雙擊安裝即可 安裝后啟動Docker提示&#xff1a;Docker Desktop -wsl kernel version too low 處理起來也是非常方便 1:管理員身份啟動&#xff1a;…