五(一)java高级-集合-集合与迭代器(二)

5.1.2 Iterator迭代器
1、Iterator
  • 所谓迭代器:就是用于挨个访问集合元素的工具/对象

方法:

  1. boolean hasNext():判断当前遍历集合后面是否还有元素可以迭代
  2. Object next():取出当前元素,并往后移→noSuchelementException
  3. void remove():删除刚刚迭代的对象
while(iterator.hasNext()){String s = (String) iterator.next();if(s.contain("a))iterator.remove();
}

Collection集合:Iterator iterator()方法

  • 返回当前遍历集合对象的一个迭代器对象,Iterator是一个接口,即返回Iterator接口的一个实现类对象,具体是哪个实现类对象,需要看集合类型。eg:Arrayist集合→返回ArrayList类中的Itr内部类,实现Iterator接口。
ArrayList arr = new ArrayList();
Iterator iterator = arr.iterator();
while(iterator.hasNext){System.out.println(iterator.next());
}
2、Iterator与Iterable

【java.lang.Iterable接口】:

  • 实现Iterable接口允许对象使用”foreach“语句进行遍历,其中数组和集合类都默认实现了Iterable接口(1.5增加)。
  • 内含的抽象方法:Iterator iterator():即实现Iterable接口本质上就是实现Iterator接口,Iterable需要依赖于Iterator。

【java.util.Iterator接口】

image-20240211150426543

3、Iterator原理
  • 删除集合元素:iterator.remove()、Collection里的removeIf()、remove(o)
//jdk1.8以后removeIf()
coll.removeIf(new Predicate(){@Overridepublic bollean test(Object o) {return (String(o)).contains("o");}
});
  • coll.remove(s):并发修改异常ConcurrentModifacationException
//2、Iterator迭代时remove()方法:
Collection coll = new ArrayList();
coll.add("hihi");
coll.add("hello");
coll.add("world");
coll.add("zhang");
coll.add("san");Iterator iterator = coll.iterator();
while (iterator.hasNext()){String s = (String) iterator.next();if(s.contains("o")){iterator.remove();//coll.remove(s);//.ConcurrentModificationException}
}
System.out.println(coll);
  • 出现漏删情况
//在foreach循环时删除
for (Object o : coll) {if(((String) o).contains("a")){coll.remove(o);//ConcurrentModificationException}
}
System.out.println(coll);

image-20240211143723226

【Iterator原理】

Iterator对象迭代元素的过程:

  1. 调用Iterator的next()之前,迭代器指向第一个元素,当第一次调用迭代器的next方法时,返回第一个元素,迭代器的索引向后移动一位,指向第二个元素;
  2. 再次调用next方法,返回第二个元素,迭代器的索引再向后移动一位,指向第三个元素;
  3. 依此类推,直到hasNext方法返回false,即全部迭代完成,结束对元素的遍历。

image-20240211150641264

【ArrayList里面源码分析】:

public Iterator<E> iterator() {return new Itr();}

创建了一个Iterator迭代器对象,返回ArrayList类中的Itr内部类,Itr内部类实现了Iterator接口。

image-20240211181355628
  • modCount:用于记录集合结构被修改的次数。
  • 对集合进行增添、删除→modCount++
  • 在用Iterator迭代器遍历集合时,创建集合迭代器的对象,会使用变量exceptionModCount记录当前集合的modCount。当进入next()方法时,会先判断exceptionModCount != modCount,如果不等于(集合结构发生了改变,modCount++)将抛出ConcurrentModificationException异常;如果相等则进行下一次迭代
private class Itr implements Iterator<E> {int cursor;       // 游标,指定当前集合索引int lastRet = -1; // 返回上一次遍历元素的索引,如果不存在为-1int expectedModCount = modCount;//迭代器创建时的modCount值Itr() {}

在ArrayList里,发现modCount变量定义在ArrayList的父类AbstractList里。在涉及add新增、remove删除、fastRemove、clear等会改变集合结构的操作,都会通过modCount++形式,增加列表在结构上被修改的次数。

//AbstractList.java
protected transient int modCount = 0;

modCount是这个list被结构性修改的次数。子类使用这个字段是可选的,如果子类希望提供fail-fast迭代器,它仅仅需要在add(int, E),remove(int)方法(或者它重写的其他任何会结构性修改这个列表的方法)中添加这个字段。调用一次add(int,E)或者remove(int)方法时必须且仅仅给这个字段加1,否则迭代器会抛出伪装的ConcurrentModificationExceptions错误。如果一个实现类不希望提供fail-fast迭代器,则可以忽略这个字。

public boolean hasNext() {return cursor != size;
}
  • 如果当前索引不等于集合大小,说明还有元素没有遍历完,返回ture将进行下一次迭代。
public E next() {checkForComodification();int i = cursor;if (i >= size)throw new NoSuchElementException();Object[] elementData = ArrayList.this.elementData;if (i >= elementData.length)throw new ConcurrentModificationException();cursor = i + 1;return (E) elementData[lastRet = i];
}
  • 检查exceptionModCount != modCount;如果相等,进入下一次迭代,不等,抛出异常。
final void checkForComodification() {if (modCount != expectedModCount)throw new ConcurrentModificationException();
}

康康remove(o)

public boolean remove(Object o) {if (o == null) {for (int index = 0; index < size; index++)if (elementData[index] == null) {fastRemove(index);return true;}} else {for (int index = 0; index < size; index++)if (o.equals(elementData[index])) {fastRemove(index);return true;}}return false;
}
private void fastRemove(int index) {modCount++;......}

image-20240211175736190

image-20240211181038290

【总结】:Iterator如何实现fail-fast机制的?

fail-fast产生的原因:在于程序在遍历过程中,某个线程对该 collection 在结构上对其做了修改,此时迭代器抛出 ConcurrentModificationException 异常信息,导致遍历失败,从而产生 fail-fast。由此可以看出fail-fast不允许在遍历的过程中对容器中的数据进行修改。

但是该异常不会始终指出对象已经由不同线程并发修改,如果单线程违反了规则,同样也有可能会抛出改异常。不能保证一定会出现该错误,但是快速失败操作会尽最大努力抛出ConcurrentModificationException异常,所以因此,为提高此类操作的正确性而编写一个依赖于此异常的程序是错误的做法,正确做法是:ConcurrentModificationException 应该仅用于检测 bug。

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

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

相关文章

S32 Design Studio的PE工具

S32 Design Studio软件是NXP公司专门为了方便用户开发S32K1系列芯片的IDE&#xff0c;跟Eclipse比较像。里面有个配套的图形工具Processor Expert&#xff0c;会产生一个后缀名为pe的文件&#xff0c;跟ST的cubemx作用类似。 双击pe文件即可打开pe界面&#xff0c;生成的文件将…

深入学习《大学计算机》系列之第1章 1.7节——图灵机的一个例子

一.欢迎来到我的酒馆 第1章 1.7节&#xff0c;图灵机的一个例子。 目录 一.欢迎来到我的酒馆二.图灵机2.1 艾伦-图灵简介2.2 图灵机简介 三.图灵机工作原理3.1 使用图灵机打印二进制数3.2 图灵机工作原理总结 四.总结 二.图灵机 本节内容主要介绍计算机科学之父——艾伦-图灵、…

基于SpringBoot、Docker和阿里云的稀土掘金社区自动签到与自动抽奖脚本:设计、开发与部署实践

创建一个SpringBoot项目 添加依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.s…

【机器学习】支持向量机(SVM)

支持向量机&#xff08;SVM&#xff09; 1 背景信息 分类算法回顾 决策树 样本的属性非数值 目标函数是离散的 贝叶斯学习 样本的属性可以是数值或非数值目标函数是连续的&#xff08;概率&#xff09; K-近邻 样本是空间&#xff08;例如欧氏空间&#xff09;中的点目标函…

Vue 进阶系列丨实现简易VueRouter

‍‍Vue 进阶系列教程将在本号持续发布&#xff0c;一起查漏补缺学个痛快&#xff01;若您有遇到其它相关问题&#xff0c;非常欢迎在评论中留言讨论&#xff0c;达到帮助更多人的目的。若感本文对您有所帮助请点个赞吧&#xff01; 2013年7月28日&#xff0c;尤雨溪第一次在 G…

PyTorch深度学习实战(26)——多对象实例分割

PyTorch深度学习实战&#xff08;26&#xff09;——多对象实例分割 0. 前言1. 获取并准备数据2. 使用 Detectron2 训练实例分割模型3. 对新图像进行推断小结系列链接 0. 前言 我们已经学习了多种图像分割算法&#xff0c;在本节中&#xff0c;我们将学习如何使用 Detectron2 …

正则表达式与正则可视化工具:解密文本处理的利器

正则表达式与正则可视化工具&#xff1a;解密文本处理的利器 引言 在计算机科学和软件开发领域&#xff0c;正则表达式是一种强大而灵活的文本处理工具。然而&#xff0c;对于初学者来说&#xff0c;正则表达式的语法和规则可能会显得晦涩难懂。为了帮助初学者更好地理解和学…

Ps:直接从图层生成文件(图像资源)

通过Ps菜单&#xff1a;文件/导出/将图层导出到文件 Layers to Files命令&#xff0c;我们可以快速地将当前文档中的每个图层导出为同一类型、相同大小和选项的独立文件。 Photoshop 还提供了一个功能&#xff0c;可以基于文档中的图层或图层组的名称&#xff0c;自动生成指定大…

2013-2022年上市公司迪博内部控制指数、内部控制分项指数数据

2013-2022年上市公司迪博内部控制指数、分项指数数据 1、时间&#xff1a;2013-2022年 2、范围&#xff1a;上市公司 3、指标&#xff1a;证券代码、证券简称、辖区、证监会行业、申万行业、内部控制指数、战略层级指数、经营层级指数、报告可靠指数、合法合规指数、资产安全…

Qt Qt Creator安装与工程介绍

一.Qt概述 什么是Qt&#xff1a;Qt是一个跨平台的C图形用户界面应用程序框架。它为应用程序开发者提供建立图形界面所需的所有功能。它是完全面向对象的&#xff0c;很容易扩展&#xff0c;并且允许真正的组件编程。 二.Qt Creator下载安装 下载地址&#xff1a;Index of /a…

openGauss学习笔记-217 openGauss性能调优-确定性能调优范围-硬件瓶颈点分析-内存

文章目录 openGauss学习笔记-217 openGauss性能调优-确定性能调优范围-硬件瓶颈点分析-内存217.1 查看内存状况217.2 性能参数分析 openGauss学习笔记-217 openGauss性能调优-确定性能调优范围-硬件瓶颈点分析-内存 获取openGauss节点的CPU、内存、I/O和网络资源使用情况&…

探索Nginx:强大的开源Web服务器与反向代理

一、引言 随着互联网的飞速发展&#xff0c;Web服务器在现代技术架构中扮演着至关重要的角色。Nginx&#xff08;发音为“engine x”&#xff09;是一个高性能的HTTP和反向代理服务器&#xff0c;也是一个IMAP/POP3/SMTP代理服务器。Nginx因其卓越的性能、稳定性和灵活性&…

无人机概述及系统组成,无人机系统的构成

无人机的定义 无人驾驶航空器&#xff0c;是一架由遥控站管理&#xff08;包括远程操纵或自主飞行&#xff09;的航空器&#xff0c;也称遥控驾驶航空器&#xff0c;以下简称无人机。 无人机系统的定义 无人机系统&#xff0c;也称无人驾驶航空器系统&#xff0c;是指一架无人…

[office] Excel表格中自动添加的超连接怎么取消? #媒体#其他#知识分享

Excel表格中自动添加的超连接怎么取消&#xff1f; Excel表格中自动添加的连接怎么取消&#xff1f;有时候在Excel2013中输入网址或邮箱时会自动添加超连接&#xff0c;本质上这是很人性化的功能&#xff0c;可是对很多人来说可能用不到&#xff0c;而且很繁琐&#xff0c;下面…

Java中“==”和equals方法的区别

目录 一、“”举例 二、equals举例 区别如下&#xff1a; &#xff08;1&#xff09;“”既可以用在基本数据类型&#xff0c;也可以用在引用数据类型&#xff1b;如果用在基本数据类型上&#xff0c;那么比较时比较的是具体的值&#xff0c;如果用在引用数据类型&#xff0c…

蓝桥云课-2024-第5场入门赛

参赛地址&#xff1a; 第 5 场 小白入门赛 - 蓝桥云课 (lanqiao.cn) 题目列表&#xff1a; 第一题&#xff1a;是签到题&#xff0c;就不需要解释了 第二题&#xff1a;欢迎参加福建省大学生程序设计竞赛&#xff08;题目&#xff09; 主要思路&#xff1a; 就是分类&#…

2023年智能可穿戴行业市场分析(电商数据查询分析):智能手表销额增长21%,手环明显下滑

近年来&#xff0c;随着技术的进步&#xff0c;智能可穿戴设备在社交网络、医疗保健、导航等诸多领域有着非常广泛的应用&#xff0c;这为大众生活带来了诸多便利。 当前的可穿戴产品形态纷繁多样&#xff0c;主要包括智能手表、智能眼镜、智能手环、健康穿戴和体感控制等等&am…

C#封装类并因此设计一个简易计算器

目录 一、涉及到的知识点 1.封装 2. 封装性的使用范围 二、实例 1.源码 2.生成效果 一、涉及到的知识点 1.封装 面向对象编程中&#xff0c;大多数都是以类作为数据封装的基本单位。类将数据和操作数据的方法结合成一个单位。设计类时&#xff0c;不希望直接存取类中的数…

MySQL数据库-MVCC多版本并发控制

mvcc,多版本并发控制&#xff08;Multi-Version Concurrency Control&#xff09;,是一种用于数据库管理系统中的并发控制方法. 在传统的并发控制方法中,如锁定机制,当一个事务修改数据时,会对相关的数据对象进行锁定,其他事务需要等待该锁释放才能进行操作。这种方法存在着事…

Stable Diffusion 模型下载:RealCartoon-Anime - V10

本文收录于《AI绘画从入门到精通》专栏,专栏总目录:点这里。 文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八案例九案例十