五(一)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://www.mzph.cn/news/679916.shtml

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

相关文章

通过容器化释放云的力量

NCSC (英国国家网络安全中心) 经常被问到的一个问题是是否在云中使用容器。这是一个简单的问题&#xff0c;但答案非常微妙&#xff0c;因为容器化的使用方式有很多种&#xff0c;其中一些方法比其他方法效果更好。 今天&#xff0c;我们发布了有关使用容器化的安全指南&#…

「深度学习」dropout 技术

一、工作原理 1. 正则化网络 dropout 将遍历网络的每一层&#xff0c;并设置消除神经网络中节点的概率。 1. 每个节点保留/消除的概率为0.5: 2. 消除节点&#xff1a; 3. 得到一个规模更小的神经网络&#xff1a; 2. dropout 技术 最常用&#xff1a;反向随机失活 "…

锐捷(二十一)全局地址绑定

vlan划分和vlanif接口配置略&#xff0c;注意vlanif接口里要no shutdown配置如下&#xff1a; Address-bind 192.168.1.1 AAAA.BBBB.CCCCAddress-bind uplink g0/0Address-bind binding-filter loggingAddress-bind install 此时&#xff0c;IP为192.168.1.1 mac地址为AAAA.B…

『运维备忘录』之 Netstat 命令详解

运维人员不仅要熟悉操作系统、服务器、网络等只是&#xff0c;甚至对于开发相关的也要有所了解。很多运维工作者可能一时半会记不住那么多命令、代码、方法、原理或者用法等等。这里我将结合自身工作&#xff0c;持续给大家更新运维工作所需要接触到的知识点&#xff0c;希望大…

GaussDB HCS 轻量化部署软件下载指引

一、Support 账号准备 1. 账号说明 华为的软件服务在华为support网站发布&#xff0c;注册该账号后&#xff0c;可以申请软件、下载离线文档&#xff0c;查看技术案例等功能 2. 账号注册 步骤 1&#xff1a;点击如下官方链接 华为运营商技术支持 - 华为 步骤 2&#xff1…

kafka教程

Kafka 中&#xff0c;Producer采用push模型&#xff0c;而Consumer采用pull模型。 Topic Topic&#xff08;主题&#xff09;是消息的逻辑分类或通道。它是Kafka中用于组织和存储消息的基本单元。一个Topic可以被看作是一个消息发布的地方&#xff0c;生产者将消息发布到一个…

机器学习9-随机森林

随机森林&#xff08;Random Forest&#xff09;是一种集成学习方法&#xff0c;用于改善单一决策树的性能&#xff0c;通过在数据集上构建多个决策树并组合它们的预测结果。它属于一种被称为“集成学习”或“集成学习器”的机器学习范畴。 以下是随机森林的主要特点和原理&…

IT行业含金量高的证书-软考

软考全称计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试&#xff0c;软考既是职业资格考试&#xff0c;又是职称资格考试。2021年12月2号发布新版的国家职业资格目录&#xff0c;软考是在计算机技术领域中的唯一的国家职业资格。 一、好处 软考是一个神奇又特…

【数据结构】14 队列(带头结点的链式存储和顺序存储实现)

定义 队列是一个有序线性表&#xff0c;但是队列的插入、删除操作是分别在线性表的两个不同端点进行的。 设一个队列 Q ( a 1 , a 2 , . . . , a n ) Q (a_1, a_2,...,a_n) Q(a1​,a2​,...,an​)&#xff0c;那么 a 1 a_1 a1​被称为队头元素&#xff0c; a n a_n an​为队…

手把手教你开发Python桌面应用-PyQt6图书管理系统-图书信息修改实现

锋哥原创的PyQt6图书管理系统视频教程&#xff1a; PyQt6图书管理系统视频教程 Python桌面开发 Python入门级项目实战 (无废话版) 火爆连载更新中~_哔哩哔哩_bilibiliPyQt6图书管理系统视频教程 Python桌面开发 Python入门级项目实战 (无废话版) 火爆连载更新中~共计24条视频&…

从互联网的公开信息中,找到属于你的赚钱思路

一、教程描述 人们在互联网上的每一次搜索、每一次关注、每一次点击、每一次点赞、每一次评论、每一次付费&#xff0c;都生成了大量的数据和信息&#xff0c;暴露着人们的真实想法、欲望、恐惧和需求。这些数据和信息&#xff0c;就是我们身边的一座“金矿”&#xff0c;而大…

1【算法】——最大子数组问题(maximum subarray)

一.问题描述 假如我们有一个数组&#xff0c;数组中的元素有正数和负数&#xff0c;如何在数组中找到一段连续的子数组&#xff0c;使得子数组各个元素之和最大。 二.问题分析 分治法求解&#xff1a; 初始状态&#xff1a; low0&#xff1b;highA.length-1&#xff1b;mid&am…

最新的 Ivanti SSRF 零日漏洞正在被大规模利用

Bleeping Computer 网站消息&#xff0c;安全研究员发现 Ivanti Connect Secure 和 Ivanti Policy Secure 服务器端请求伪造 (SSRF) 漏洞&#xff08;CVE-2024-21893 &#xff09;正在被多个威胁攻击者大规模利用。 2024 年 1 月 31 日&#xff0c;Ivanti 首次就网关 SAML 组件…

万维网的文档

目录 1 万维网的文档 动态万维网文档 CGI CGI 网关程序 活动万维网文档 用 Java 语言创建活动文档 1 万维网的文档 分为&#xff1a; 静态万维网文档。内容不会改变。简单。(html、xml、css) 动态万维网文档。文档的内容由应用程序动态创建。 活动万维网文档。由浏览器端…

SpringBoot3整合Knife4j

前置&#xff1a; 官网&#xff1a;快速开始 | Knife4j gitee&#xff1a;swagger-bootstrap-ui-demo: knife4j 以及swagger-bootstrap-ui 集成框架示例项目 - Gitee.com 1.依赖引入&#xff1a; ps&#xff1a;json处理需要引入相关包 <dependency><groupId>c…

基于语义解析的知识图谱问答系统

目录 前言1 背景介绍2 语义解析的核心技术2.1 自然语言处理&#xff08;NLP&#xff09;2.2 语义表示学习2.3 实体关系抽取 3 语义解析的基本步骤3.1 短语检测3.2 资源映射3.3 语义组合3.4 逻辑表达式生成 4 处理与知识图谱无关的问句4.1 Bridging技术4.2 确定谓词4.3 Paraphra…

【新书推荐】7.4节 寄存器间接和相对寻址方式

本节内容&#xff1a;当指令操作数为内存操作数&#xff0c;且内存操作数的地址使用指针寄存器表示时&#xff0c;称为寄存器间接寻址方式。 ■寄存器间接寻址方式&#xff1a;在地址表达式中&#xff0c;只能使用BX、SI、DI、BP四个指针寄存器用来寻址。 7.4.1 寄存器间接寻…

猫头虎分享已解决Bug || API限制超额(API Rate Limiting):RateLimitExceeded, APILimitReached

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

mysql入门到精通006-基础篇-多表查询

1、多表关系介绍 1.1 概念 项目开发中&#xff0c;在进行数据库表结构设计时&#xff0c;会根据业务需求和业务模块之间的关系&#xff0c;分析并设计表结构&#xff0c;由于业务之间相互关联&#xff0c;所以各个表结构之间也存在各种联系&#xff0c;基本上分为3种&#xf…

LeetCode.144. 二叉树的前序遍历

题目 144. 二叉树的前序遍历 分析 这道题目是比较基础的题目&#xff0c;我们首先要知道二叉树的前序遍历是什么&#xff1f; 就是【根 左 右】 的顺序&#xff0c;然后利用递归的思想&#xff0c;就可以得到这道题的答案&#xff0c;任何的递归都可以采用 栈 的结构来实现…