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.rhkb.cn/news/96577.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

记一次fegin调用的媒体类型问题

1.问题&#xff1a;分页查询&#xff0c;分页参数传递不生效 2.开发环境&#xff1a;fegin接口 开发环境&#xff1a;调用接口 3.修改后&#xff1a;fegin接口不变 调用接口 前端媒体类型&#xff1a; 问题解决&#xff01;&#xff01;&#xff01; 4.原因分析&…

开源数据库Mysql_DBA运维实战 (备份与还原)

Mysql数据库的备份与还原&#x1f343; 备份对于数据库而言是至关重要的。当数据文件发生损坏、MySQL服务出现错误、系统内核崩溃、计算机硬件损坏或者数据被误删等事件时&#xff0c;使用一种有效的数据备份方案&#xff0c;就可以快速解决以上所有的问题。MySQL提供了多种备…

mongodb数据库

目录 一、数据库 二、文档 三、集合 四、元数据 五、MongoDB 数据类型 1、ObjectId 2、字符串 3、时间戳 4、日期 一、数据库 一个 mongodb 中可以建立多个数据库。 MongoDB 的默认数据库为"db"&#xff0c;该数据库存储在 data 目录中。 MongoDB 的单…

跨境电商平台(例如阿里巴巴、虾皮)的商品数据如何收集?

跨境电商是指通过互联网&#xff0c;以跨越国家或地区边界的方式进行电子商务交易的商业行为。传统的电子商务通常是在同一国家或地区内进行&#xff0c;而跨境电商则侧重于跨国贸易。跨境电商通过在线平台&#xff08;如阿里巴巴、亚马逊等&#xff09;或第三方服务商&#xf…

Openlayers 实战 - 地图视野(View)- 图层 -(layer)- 资源(source)显示等级设置

Openlayers 实战 - 地图视野&#xff08;View&#xff09;- 图层 -&#xff08;layer&#xff09;- 资源&#xff08;source&#xff09;显示等级设置 问题原因核心代码完整代码&#xff1a;在线示例 在以往的项目维护中&#xff0c;出现一个问题&#xff0c;使用最新高清底图发…

CSS:filter滤镜 详解(用法 + 代码 + 例子 + 效果)

文章目录 filter 滤镜blur() 模糊度例子 渐变光晕 brightness() 元素亮度contrast() 对比度grayscale() 元素灰度hue-rorate() 色相opacity() 透明度invert() 反转颜色saturate() 饱和度 backdrop-filter 蒙版&#xff0c;滤镜例子 卷轴展开 filter 滤镜 动图为效果添加前后对…

前馈神经网络正则化例子

直接看代码&#xff1a; import torch import numpy as np import random from IPython import display from matplotlib import pyplot as plt import torchvision import torchvision.transforms as transforms mnist_train torchvision.datasets.MNIST(root…

产品经理必知必会0.2

Q1:产品经理需要具备的能力&#xff1f; A:硬实力&#xff1a;产品设计、需求分析、竞品分析、数据分析、撰写文档 软实力&#xff1a;沟通能力、学习能力、用户思维、主动性、好奇心、同理心、责任心、抗压能力、目标导向.... 扩展能力&#xff1a;商业思维、市场敏感度... Q…

hive高频使用的拼接函数及“避坑”

hive高频使用的拼接函数及“避坑” 说到拼接函数应用场景和使用频次还是非常高&#xff0c;比如一个员工在公司充当多个角色&#xff0c;我们在底层存数的时候往往是多行&#xff0c;但是应用的时候我们通常会只需要一行&#xff0c;角色字段进行拼接&#xff0c;这样join其他…

STM32 F103C8T6学习笔记8:0.96寸单色OLED显示屏显示字符

使用STM32F103 C8T6 驱动0.96寸单色OLED显示屏: OLED显示屏的驱动&#xff0c;在设计开发中OLED显示屏十分常见&#xff0c;因此今日学习一下。一篇文章从程序到显示都讲通。 文章提供源码、原理解释、测试工程下载&#xff0c;测试效果图展示。 目录 OLED驱动原理—IIC通信…

通讯录实现【C语言】

目录 前言 一、整体逻辑分析 二、实现步骤 1、创建菜单和多次操作问题 2、创建通讯录 3、初始化通讯录 4、添加联系人 5、显示联系人 6、删除指定联系人 ​7、查找指定联系人 8、修改联系人信息 9、排序联系人信息 三、全部源码 前言 我们上期已经详细的介绍了自定…

mongodb.使用自带命令工具导出导入数据

在一次数据更新中&#xff0c;同事把老数据进行了清空操作&#xff0c;但是新的逻辑数据由于某种原因&#xff08;好像是她的电脑中病毒了&#xff09;&#xff0c;一直无法正常连接数据库进行数据插入&#xff0c;然后下午2点左右要给甲方演示&#xff0c;所以要紧急恢复本地的…

于vue3+vite+element pro + pnpm开源项目

河码桌面是一个基于vue3viteelement pro pnpm 创建的monorepo项目&#xff0c;项目采用的是类操作系统的web界面&#xff0c;操作起来简单又方便&#xff0c;符合用户习惯&#xff0c;又没有操作系统的复杂&#xff01; 有两个两个分支&#xff0c;一个是web版本&#xff0c;…

机器学习深度学习——机器翻译(序列生成策略)

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位即将上大四&#xff0c;正专攻机器学习的保研er &#x1f30c;上期文章&#xff1a;机器学习&&深度学习——seq2seq实现机器翻译&#xff08;详细实现与原理推导&#xff09; &#x1f4da;订阅专栏&#xff1a;机…

【Freertos基础入门】队列(queue)的使用

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、队列是什么&#xff1f;二、队列的操作二、示例代码总结 前言 本系列基于stm32系列单片机来使用freerots FreeRTOS是一个广泛使用的开源实时操作系统&…

Linux网络编程:Socket套接字编程

文章目录&#xff1a; 一&#xff1a;定义和流程分析 1.定义 2.流程分析 3.网络字节序 二&#xff1a;相关函数 IP地址转换函数inet_pton inet_ntop&#xff08;本地字节序 网络字节序&#xff09; socket函数(创建一个套接字) bind函数(给socket绑定一个服务器地址结…

企业数据库遭到360后缀勒索病毒攻击,360勒索病毒解密

在当今数字化时代&#xff0c;企业的数据安全变得尤为重要。随着数字化办公的推进&#xff0c;企业的生产运行效率得到了很大提升&#xff0c;然而针对网络安全威胁&#xff0c;企业也开始慢慢引起重视。近期&#xff0c;我们收到很多企业的求助&#xff0c;企业的服务器遭到了…

go 协程并发数控制

错误的写法&#xff1a; 这里的<-ch 是为了从channel 中读取 数据&#xff0c;为了不使channel通道被写满&#xff0c;阻塞 go 协程数的创建。但是请注意&#xff0c;go workForDraw(v, &wg) 是不阻塞后续的<-ch 执行的&#xff0c;所以就一直go workForDraw(v, &…

Find My资讯|苹果Vision Pro开发者需将设备配对 AirTag

最近苹果Vision Pro获开发者申请&#xff0c;苹果要求获批的申请者使用 Measure and Fit 应用确认合适的佩戴尺寸&#xff0c;并会根据申请者提交的信息&#xff0c;定制不同的 Vision Pro 开发者套件&#xff0c;以便于契合申请者的面部特征&#xff0c;提供更好的佩戴体验。 …

iPhone 15受益:骁龙8 Gen 3可能缺席部分安卓旗舰机

明年一批领先的安卓手机的性能可能与今年的机型非常相似。硅成本的上涨可能是原因。 你可以想象&#xff0c;2024年许多最好的手机都会在Snapdragon 8 Gen 3上运行&#xff0c;这是高通公司针对移动设备的顶级芯片系统的更新&#xff0c;尚未宣布。然而&#xff0c;来自中国的…