Java 入门指南:迭代器(Iterator)

news2025/1/18 9:48:48

迭代器

迭代器(Iterator) 是一种行为型设计模式,属于设计模式之一,迭代器模式提供了一种方法来顺序访问一个聚合对象(如List、Set等)中各个元素,而不需要暴露该对象的内部表示。

  • Iterator 对象称为迭代器,主要用于遍历 Collection 集合中的元素。

  • 所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象,即可以返回一个迭代器。

  • Iterator 仅用于遍历集合,Iterator 本身并不存放对象。

  • 集合的顶层接口 Collection 继承 Iterable 接口。

迭代器的特性

  • fail-fast机制:当集合在迭代过程中被修改(除了通过迭代器自身的remove()方法),迭代器会快速失败,抛出ConcurrentModificationException

  • fail-safe机制:某些集合(如 CopyOnWriteArrayList )的迭代器是 fail-safe 的,即它们允许在迭代过程中修改集合,但修改会反映在一个新的集合副本上,不会影响迭代器遍历的集合。

Iterable 和 Iterator 接口

Iterable接口

public interface Iterable<T> {
    /**
     * Returns an iterator over elements of type {@code T}.
     *
     * @return an Iterator.
     */
    Iterator<T> iterator();
}

Iterable 接口中有一个 Iterator 方法,它返回一个 Itertator 对象。

Iterator接口

public interface Iterator<E> {
    boolean hasNext();
    
    E next();
    
    default void remove() {
        throw new UnsupportedOperationException("remove");
    }
}
返回值类型方法名功能
booleanhasNext()判断集合是否还有元素,如果返回 true 表示集合还有元素,返回 false 表示集合中没有元素;一般对集合的访问通过 while(hasNext()) 判断是否还需要遍历。
Enext()获取集合中遍历的当前元素 ;一般先调用 hasNext() 方法判断是否存在元素,再调用 next() 获取元素,需要进行循环交替遍历集合中的元素。
voidremove删除集合中的元素。
使用迭代器遍历
Collection col = new ArrayList();

Iterator iterator = col.iterator(); // 创建迭代器对象
// 判断集合是否有下一个元素
while(iterator.hasNext()){
	// 指针移动一个位置,返回集合该位置的元素
	Object tmp = iterator.next();
}

在调用 next() 方法之前必须要调用 hastNext() 方法进行检测;如果没有调用并且没有下一个元素,直接调用 next() 方法会抛出 NoSuchElementException异常

遍历完毕后,若继续调用 iterator.hasNext() 将会报错,若需要继续遍历,可以通过重置迭代器(创建一个新的迭代器或使用可重复迭代器)解决

使用增强 for 循环 遍历

增强for循环 可以代替 Iterator 迭代器 ,可以把它看做简化版的 Iterator,和迭代器本质一样,它的底层实现就是 Iterator 迭代器,只能用于遍历集合或数组

for(Object object : col){
	// 对 object 进行操作
}
迭代器中的 remove 方法

使用迭代器的 remove 的方法可以删除集合中的元素

在Java集合中,以集合 ArrayList 为例,在使用中可能会遇到删除的需求场景,此时如果代码书写不当,极有可能会抛出java.util.ConcurrentModificationException异常信息。因为触发了集合中并发修改的异常

ArrayList 集合的 Iterator 方法中,是通过返回 Itr 对象来获得迭代器的。Itr ArrayList 的一个内部类,它实现了 Iterator 接口

![[Pasted image 20231018095155.png]]

![[Pasted image 20231018095212.png]]

属性含义
cursor索引下标,表示下一个可以访问的元素的索引,默认值为 0
lastRet索引下标,表示上一个元素的索引,默认值为 -1
expectedModCount对集合修改的版本号,初始值为ModCount

ModCount 定义在 AbstractList 接口中,初始值为0,在对集合进行变更操作(增加、删除、修改等)的时候会对版本号进行 +1 操作。:

protected transient int modCount = 0;

![[Pasted image 20231018095409.png]]

  • 在使用迭代器的 remove() 操作时,会将更新后的 modCount 给expectedModCount,两者会得到同步,但是在调用集合的 remove() 方法后,两个不会进行同步,进而导致在 checkForComodification() 校验时不通过,抛出 java.util.ConcurrentModificationException 异常。

  • 在单线程下使用迭代器是没有问题的,但是在多线程下同时操作集合就不允许了,可以通过 fail-fast 快速失败机制,快速判断是否存在同时操作问题。因此,集合在多线程下使用是不安全的

for…each 的陷阱

为什么不能在 foreach 里执行删除操作?

因为 for...each 循环是基于迭代器实现的,而迭代器在遍历集合时会维护一个 expectedModCount 属性来记录集合被修改的次数。
如果在 for...each 循环中执行删除操作会导致 expectedModCount 属性值与实际的 modCount 属性值不一致,从而导致迭代器的 hasNext()next() 方法抛出 ConcurrentModificationException 异常。

为了避免这种情况,应该使用迭代器的 remove() 方法来删除元素,该方法会在删除元素后更新迭代器状态,确保循环的正确性。如果需要在循环中删除元素,应该使用迭代器的 remove() 方法,而不是集合自身的 remove() 方法

除此之外,还可以采用 Stream流 的 filter() 方法来过滤集合中的元素,然后再通过 collect() 方法将过滤后的元素收集到一个新的集合中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2070257.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

攻防世界-web题型-6星难度汇总-个人wp

i-got-id-200 这一题很清楚的告诉了考点是什么&#xff0c;就是cgi相关的知识&#xff0c;不过我对这个不了解。。。也不会perl语言&#xff0c;先去网上看看这个东西吧&#xff0c;了解一下 看到一篇挺有意思的视频CGI&#xff08;通用网关接口&#xff09;_百度百科 看了这…

MediaTek 天玑9000 旗舰5G,都有哪些突破

天玑9000&#xff0c;是MTK 在2022发布的全新旗舰SOC , 采用台积电4nm制程和Armv9架构,八核CPU。 市场上采用天玑9000的手机有小米12Pro、小米Redmi K50 Pro、Vivo X80等。 今天我们看下这款soc更详细的一些特点介绍。 一、率先采用台积电 4nm 先进制程 业界率先采用台积电 4nm…

传统2D3D视觉分享

哈喽&#xff0c;大家好&#xff0c;本文主要是说明关于【视觉源码小铺】知识星球内的相关内容 视觉源码小铺都有什么内容 IVision拖拽平台&算法 星球内算法&#xff08;持续更新&#xff09;

滚雪球学Java(90):Java图形界面新篇章:Swing框架深度解析,真有点东西!

咦咦咦&#xff0c;各位小可爱&#xff0c;我是你们的好伙伴——bug菌&#xff0c;今天又来给大家普及Java SE啦&#xff0c;别躲起来啊&#xff0c;听我讲干货还不快点赞&#xff0c;赞多了我就有动力讲得更嗨啦&#xff01;所以呀&#xff0c;养成先点赞后阅读的好习惯&#…

解决MySQL的PacketTooBigException异常问题

一、背景 在大数据量导入mysql的时候&#xff0c;提示错误Cause: com.mysql.cj.jdbc.exceptions.PacketTooBigException: Packet for query is too large 原因是MySQL的max_allowed_packet设置最大允许接收的数据包过小引起的&#xff0c;默认的max_allowed_packet如果不设置&…

Stable Diffusion 使用详解(9)--- 艺术字及海报融入

目录 背景 方法一 利用controlNet lineart invert depth 提示词 效果 方法二 准备蒙版 绘制大型场景艺术字 controlnet Lora 模型 效果 PS 融入 背景 如果看过上一期你应该知道如何利用layer diffusion 制作场景动漫海报&#xff0c;其实掌握这个方法后&#xf…

DFS 算法:记忆化搜索

我的个人主页 {\large \mathsf{{\color{Red} 我的个人主页} } } 我的个人主页 往 {\color{Red} {\Huge 往} } 往 期 {\color{Green} {\Huge 期} } 期 文 {\color{Blue} {\Huge 文} } 文 章 {\color{Orange} {\Huge 章}} 章 无 此系列更新频繁&#xff0c;求各位读者点赞 关…

视频号小店:微信生态下的新零售革命者

在数字化浪潮的席卷之下&#xff0c;微信视频号凭借其独特的社交基因和庞大的用户群落&#xff0c;正悄然崛起为新零售战场上的新晋强者。特别是视频号小店体系的创立&#xff0c;为商家打造了一个集商品展现、交易促进与营销策略部署于一体的综合运营平台&#xff0c;实现了业…

网络安全中的人工智能应用

1. 引言 随着网络攻击的复杂性和频率不断增加&#xff0c;传统的安全防护措施逐渐难以应对这些威胁。人工智能&#xff08;AI&#xff09;作为一种变革性的技术&#xff0c;正在逐步成为增强网络安全的重要工具。AI通过自动化、智能化的方式&#xff0c;可以有效提高威胁检测、…

【JAVA基础】多态

文章目录 多态向上转型练习题 多态 父类的引用指向子类的对象 public class A {public String name;public int age;public void run(){ //该run()方法被覆盖System.out.println("a跑的快");}public void eat(String name){System.out.println(name"吃的很多&…

从零到一,我的AI绘画赚钱之旅:准大一新生暑假自学成才,月入学费不是梦!

大家好&#xff0c;我是即将步入大学校园的准大一新生。在这个漫长的暑假里&#xff0c;我决定学习一门新技术&#xff0c;充实自己。在一次网上冲浪的过程中&#xff0c;我偶然发现了AI绘画这个神奇的世界。以下是我在暑假期间学习AI绘画的经历&#xff0c;以及我是如何通过它…

缓存之Tair

介绍 ​ 在Tair出现之前的很长一段时间里&#xff0c;像redis、memcache这些知名NoSql数据库是不支持分布式的&#xff0c;在这样的背景下&#xff0c;由淘宝网自主开发并在2010.6开源的一个高性能、高扩展、高可靠分布式缓存&#xff0c;类似map的key/value结构&#xff0c;在…

C#实现数据采集系统-数据反写(3)ModbusTcp写入数据模块开发

写入报文分析 ModbusTcp报文详细解析见 ModbusTCP协议报文解析 写入常用的四个功能码&#xff0c;线圈 05,15&#xff08;0x0F&#xff09;,寄存器06,16&#xff08;0x10&#xff09; 详细报文如下&#xff1a; //00 01 00 00 00 06 FF 05 00 01 FF 00 写单个线圈 //00 01 …

【人工智能】AI虚拟主播制作初体验:生成数字人到视频创作全流程

文章目录 &#x1f4af;AI虚拟主播&#x1f4af;使用AI绘画工具生成数字人借助GPT生成数字人所需的提示词方案一&#xff1a;使用Midjourney生成数字人方案二&#xff1a;使用TensAI生成数字人补充方案三&#xff1a;在D-ID内直接生成数字人 &#x1f4af;使用D-ID生成数字人视…

CS1.5快捷键

《黑神话悟空》玩不起&#xff0c;玩起了23年前的cs1.5 B11&#xff1a;USP(警察自带手枪&#xff09; B12&#xff1a;Glock18(匪徒自带手枪) B13&#xff1a;Desert Eagle&#xff08;沙漠之鹰&#xff09; B14&#xff1a;P-228 B15&#xff1a;Dual Berettas&#xff08;匪…

git命令大全(git checkout ,git merge,git branch,git cherry-pick)

git stash 和git commit区别git文件状态命令手册git init git clone提交和修改git log远程仓库操作 git pull git push创建分支&#xff08;增删改查&#xff09;git checkout ,git branch ,git mergegit loggit taggit add, git stash ,git rebase,git cherry-pick git stash …

AI绘画SD三分钟入门教程!秋叶大佬8月最新的Stable Diffusion整合包V4.9来了,完整安装部署教程奉上,附各种模型插件一次性用爽!

大家好&#xff0c;我是画画的小强 前几天8月15日&#xff0c;国内AI绘画工具开源大佬更新了StableDiffusion整合包最新版本4.9&#xff0c;相关信息从图中能看到&#xff0c;本次更新后SD WebUI已经能够支持最新的AI绘画大模型SD3.0&#xff0c;以及更新了SD最强的控制插件Co…

nvm 安装老的node,npm版本

1、今天想安装一个老的node与npm版本&#xff0c;但出现问题&#xff0c;安装不了 2、后来修改settings.txt文件增加如下&#xff1a; node_mirror: https://npmmirror.com/mirrors/node/ npm_mirror: https://npmmirror.com/mirrors/npm/ 否则因为现在访问https://nodejs.or…

Jmeter 性能测试实战教程

一、性能测试流程 进行性能测试前&#xff0c;我们首先需要了解一下性能测试大致分为哪些流程&#xff0c;这样才能保证测试过程有序开展&#xff1a; 1、性能需求分析 了解哪些业务需要&#xff08;一般都是用户量大的核心业务&#xff0c;比如登录&#xff0c;查询等功能&…

HTML5休闲小游戏《切割大师》源码,引流、刷广告利器

HTML5休闲小游戏《切割大师》源码&#xff0c;直接把源码上传到服务器就能使用了&#xff01; 下载链接&#xff1a;https://www.huzhan.com/code/goods467910.html