Java迭代器详解,看这一篇就够了

文章目录
🚩Java 迭代器详解
📚迭代器的定义
📒认识Iterator
✏️类结构图
✒️Iterable接口
🖍️Iterator接口
📃Iterator接口的方法
📙迭代器的使用
🏷️使用迭代器遍历集合
🔖Itertor的执行原理
⏳图示执行过程
⌛执行过程详解
🃏生成迭代器的快捷键
📕迭代器中的remove()
⛄迭代器的remove()方法使用
☃️迭代器遍历中调用集合revome()方法触发异常
📗增强for循环
📫认识增强for循环
📪基本语法
📬增强for循环的使用
📭增强for循环的快捷键

🚩Java 迭代器详解
📚迭代器的定义
迭代器是属于设计模式之一,迭代器模式提供了一种方法来顺序访问一个聚合对象中各个元素,而不保留该对象的内部表示。

1)Iterator对象称为迭代器,主要用于遍历Collection集合中的元素。
2)所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象,即可以返回一个迭代器。
3)Iterator仅用于遍历集合,Iterator本身并不存放对象。

📒认识Iterator
✏️类结构图

 通过观察类结构图的继承关系我们发现,集合的顶层接口Collection继承Iterable接口。

✒️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");}
}
📃Iterator接口的方法
返回值类型方法名功能
booleanhasNext()判断集合是否还有元素,如果返回 true 表示集合还有元素,返回 false 表示集合中没有元素;一般对集合的访问通过 while(hasNext()) 判断是否还需要遍历。
Enext()获取集合中遍历的当前元素 ;一般先调用 hasNext() 方法判断是否存在元素,再调用 next() 获取元素,需要进行循环交替遍历集合中的元素。
voidremove删除集合中的元素。

📙迭代器的使用

🏷️使用迭代器遍历集合

我们用ArrayList集合存放一些整型数据做示例,然后将其集合中的元素一一遍历打印输出。

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;public class TestDemo {public static void main(String[] args) {List<Integer> list = new ArrayList<>();list.add(111);list.add(222);list.add(333);Iterator<Integer> iterator = list.iterator();while(iterator.hasNext()) {int value = iterator.next();System.out.print(value + " ");}}
}

运行结果:

观察运行结果我们发现,通过迭代器我们将ArrayList集合中的元素一一打印了出来。

🔖Itertor的执行原理

在上述的示例中,迭代器是如何实现对集合的遍历呢?

⏳图示执行过程

 ⌛执行过程详解
①首先得到一个集合的迭代器Iterator iterator = list.iterator();
②进入while循环,调用hasNext()判断是否有下一个元素,返回true,Iterator.next()移动一个位置,将该位置的元素111返回。
③再次进入while循环,调用hasNext()判断是否有下一个元素,返回true,Iterator.next()移动一个位置,将该位置222的元素返回。
④再次进入while循环,调用hasNext()判断是否有下一个元素,返回true,Iterator.next()移动一个位置,将该位置333的元素返回。
⑤再次进入while循环,调用hasNext()判断是否有下一个元素,返回false,循环结束。

在 迭代器的遍历过程中先通过hastNext()方法判断是否有下一个元素,如果存在下一个元素再调用next()方法获取元素,在这里next()方法先往后移动一个元素位置,再返回该位置的元素。因此,在调用next()方法之前必须要调用hastNext()方法进行检测;如果没有调用并且没有下一个元素,直接调用next()方法会抛出 NoSuchElementException异常。

🃏生成迭代器的快捷键
一开始使用迭代器可能会觉得麻烦,但是如果用的Idea编译器是有快捷键的,输入itit再回车就会直接生成。

📕迭代器中的remove()

⛄迭代器的remove()方法使用

在Iterator接口中除了hasNext()next()方法外,还有一个remove()方法,即删除集合中的元素

如删除上述示例集合中的元素111

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@SuppressWarnings({"all"})
public class TestDemo {public static void main(String[] args) {List<Integer> list = new ArrayList<>();list.add(111);list.add(222);list.add(333);System.out.println("删除前:" + list);Iterator<Integer> iterator = list.iterator();while (iterator.hasNext()) {Integer value =  iterator.next();if(value == 111) iterator.remove();}System.out.println("删除后" + list);}
}

运行结果:

☃️迭代器遍历中调用集合revome()方法触发异常
在Java集合中,以集合ArrayList为例,在使用中可能会遇到删除的需求场景,此时如果代码书写不当,极有可能会抛出java.util.ConcurrentModificationException异常信息。
在上述示例中用Iterator调用了迭代器remove()方法,如果在使用中不小心调用了集合中的remove()方法会发生什么?

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@SuppressWarnings({"all"})
public class TestDemo {public static void main(String[] args) {List<Integer> list = new ArrayList<>();list.add(111);list.add(222);list.add(333);System.out.println("删除前:" + list);Iterator<Integer> iterator = list.iterator();while (iterator.hasNext()) {Integer value =  iterator.next();if(value == 111) list.remove(Integer.valueOf(111));}System.out.println("删除后" + list);}
}

运行结果:

运行结果中抛出java.util.ConcurrentModificationException异常信息。这是因为触发了集合中并发修改的异常 接下来我们通过源码对抛出异常的原因进行剖析。

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

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

   private class Itr implements Iterator<E> {int cursor;       // index of next element to returnint lastRet = -1; // index of last element returned; -1 if no suchint expectedModCount = modCount;Itr() {}public boolean hasNext() {return cursor != size;}@SuppressWarnings("unchecked")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];}public void remove() {if (lastRet < 0)throw new IllegalStateException();checkForComodification();try {ArrayList.this.remove(lastRet);cursor = lastRet;lastRet = -1;expectedModCount = modCount;} catch (IndexOutOfBoundsException ex) {throw new ConcurrentModificationException();}}

Itr类属性

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

 ModCount定义在AbstractList接口中,初始值为0,定义如下:

 protected transient int modCount = 0;

ModCount是版本号,在对集合进行变更操作(增加、删除、修改等)的时候会对版本号进行 +1 操作。


结合上述代码进行抛出java.util.ConcurrentModificationException异常的解释。
①初始化ArrayList,添加三次元素,即三次调用add()方法,进行三次modCount++; 此时,m o d C o u n t = 3 , s i z e = 3 ; \color{red}{modCount = 3,size = 3;}modCount=3,size=3;
②初始化Iterator迭代器进行循环,此时,e x p e c t e d M o d C o u n t = m o d C o u n t = 3 , \color{red}{expectedModCount = modCount=3,}expectedModCount=modCount=3, c u r s o r = 0 , l a s t R e t = − 1 \color{red}{cursor=0,lastRet = -1}cursor=0,lastRet=−1
③进行hasNext判断,cursor != size;成立,进入循环
④调用next()方法,首先进行checkForComodification()校验,m o d C o u n t = = e x p e c t e d M o d C o u n t \color{red}{modCount == expectedModCount}modCount==expectedModCount,校验通过,返回值,此时l a s t R e t = 0 ; c u r s o r = 1 \color{red}{lastRet = 0;cursor = 1}lastRet=0;cursor=1
 

 final void checkForComodification() {if (modCount != expectedModCount)throw new ConcurrentModificationException();}

⑤调用集合remove()方法,modCount++;,此时m o d C o u n t = 4 ; s i z e = 2 \color{red}{modCount = 4;size = 2}modCount=4;size=2
⑥再次调用hasNext()方法判断,cursor != size;成立,进入循环
⑦调用next()方法进行校验,m o d C o u n t ! = e x p e c t e d M o d C o u n t \color{red}{modCount != expectedModCount}modCount!=expectedModCount,校验未通过,抛出java.util.ConcurrentModificationException异常

总结:

①在使用迭代器的remove()操作时,会将更新后的modCount给expectedModCount,两者会得到同步,但是在调用集合的remove()方法后,两个不会进行同步,进而导致在checkForComodification()校验时不通过,抛出java.util.ConcurrentModificationException异常。
②所以,在单线程下使用迭代器是没有问题的,但是在多线程下同时操作集合就不允许了,可以通过fail-fast快速失败机制,快速判断是否存在同时操作问题。因此,集合在多线程下使用是不安全的。

📗增强for循环

📫认识增强for循环

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

📪基本语法

📬增强for循环的使用

import java.util.ArrayList;
import java.util.List;public class TestDemo03 {public static void main(String[] args) {List<Integer> list = new ArrayList<>();list.add(111);list.add(222);list.add(333);System.out.println("====增强for循环遍历集合====");for(Integer i : list) {System.out.print(i + " ");}System.out.println();System.out.println("====增强for循环遍历数组====");int[] arr = {1,2,3,4,5,6};for (int i : arr) {System.out.print(i + " ");}}
}

 运行结果:

📭增强for循环的快捷键

与迭代器一样,增强for循环也有快捷键,输入I回车即可快速生成。


原文链接:https://blog.csdn.net/sheng0113/article/details/122712947

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

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

相关文章

[BIZ] - 1.金融交易系统特点

1. 典型数据汇总 数据 说明 新增数据量(条/天) Qps(条/s) 消息大小(Byte) 实时性 可丢失性 可恢复性 实时行情 1.使用场景&#xff1a;交易&#xff0c;报价&#xff0c;策略验证&#xff1b; 2.冷热分离&#xff1a;彭博行情/其他行情&#xff1b;黄金&期货行情/…

Java图形化界面编程——AWT概论 笔记

2.3 Container容器 2.3.1 Container继承体系 Winow是可以独立存在的顶级窗口,默认使用BorderLayout管理其内部组件布局;Panel可以容纳其他组件&#xff0c;但不能独立存在&#xff0c;它必须内嵌其他容器中使用&#xff0c;默认使用FlowLayout管理其内部组件布局&#xff1b;S…

交通管理|交通管理在线服务系统|基于Springboot的交通管理系统设计与实现(源码+数据库+文档)

交通管理在线服务系统目录 目录 基于Springboot的交通管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、用户信息管理 2、驾驶证业务管理 3、机动车业务管理 4、机动车业务类型管理 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计…

MySQL学习Day15——MySQL安装与使用

一、Linux下的MySQL的安装与使用: 卸载MySQL: 1.关闭当前MySQL服务:systemctl stop mysql.service 2.查看当前mysql安装状况:rpm -qa | grep -i mysql 3.卸载上述命令查询出的已安装的程序:yum remove mysql-xxx mysql-xxx mysql-xxxx 4.删除mysql相关文件: (1)查找相关文…

解决vscode报错,在赋值前使用了变量“XXX“

问题&#xff1a;如图所示 解决方法&#xff1a; 法一&#xff1a; 补全函数使其完整 法二&#xff1a; 使用断言

c++Qt网络操作

1、基础概念 1.1 TCP/UDP TCP 是一种面向连接的传输层协议&#xff0c;它能提供高可靠性通信(即数据无误、数据无丢失、 数据无失序、数据无重复到达的通信) 适用情况&#xff1a; 1.SN/QQ等即时通讯软件的用户登录账户管理相关的功能通常采用TCP协议 2、适合于对传输质量要求较…

【STM32 CubeMX】串口编程DMA

文章目录 前言一、DMA方式1.1 DMA是什么1.2 CubeMX配置DMA1.3 DMA方式函数使用DMA的发送接收函数 总结 前言 在嵌入式系统中&#xff0c;串口通信是一项至关重要的功能&#xff0c;它允许单片机与外部设备进行数据交换&#xff0c;如传感器、显示器或其他设备。然而&#xff0…

Linux笔记之xhost +和docker的关系以及GDK_SCALE和GDK_DPI_SCALE详解

Linux笔记之xhost 和docker的关系以及GDK_SCALE和GDK_DPI_SCALE详解 ——2024-02-11 code review! 文章目录 Linux笔记之xhost 和docker的关系以及GDK_SCALE和GDK_DPI_SCALE详解xhost 的作用xhost 与 Docker 的关系 -e GDK_SCALE 和 -e GDK_DPI_SCALE详解GDK_SCALEGDK_DPI_SC…

【Linux】进程的初步认识

进程的初步认识 基本概念描述进程task_struct-PCB的一种task_stuct内容分类 查看进程通过系统调用获取进程标识符 基本概念 要了解进程&#xff0c;首先我们要知道两点 我们可以同时启动多个程序&#xff0c;也就意味着我们可以将多个.exe文件加载到内存操作系统如何去管理这些…

036-安全开发-JavaEE应用第三方组件Log4j日志FastJson序列化JNDI注入

036-安全开发-JavaEE应用&第三方组件&Log4j日志&FastJson序列化&JNDI注入 #知识点&#xff1a; 1、JavaEE-组件安全-Log4j 2、JavaEE-组件安全-Fastjson 3、JavaEE-基本了解-JNDI-API 演示案例&#xff1a; ➢Java-三方组件-Log4J&JNDI ➢Java-三方组件-Fa…

OpenAI全新发布文生视频模型Sora - 现实,不存在了

OpenAI&#xff0c;发他们的文生视频大模型&#xff0c;Sora了。。。。。 而且&#xff0c;是强到&#xff0c;能震惊我一万年的程度。。。 https://openai.com/sora 如果非要用三个词来总结Sora&#xff0c;那就是“60s超长长度”、“单视频多角度镜头”和“世界模型” &am…

Codeforces Round 926 (Div. 2)(A,B,C,D,E,F)

这场还是很有含金量的&#xff0c;B题开始就有难度了&#xff0c;B是个推结论的题&#xff0c;C要推结论然后递推&#xff0c;D题是有点难的树上DP&#xff08;主要是状态转移方程不好写&#xff09;&#xff0c;E题是个二进制预处理然后状压DP&#xff0c;F题是个数论&#xf…

写一个程序,输入数量不确定的[0,9]范围内的整数,统计每一种数字出现的次数输入-1表示结束

#include <stdio.h> int main(void) {int x;int count[10];int i;for(i0;i<10;i){//初始化数组 count[i]0;}scanf("%d",&x);while(x!-1){if( x>0 && x<9){count[x];//数组参与运算 }scanf("%d",&x);}for(i0;i<10;i){pr…

车载诊断协议DoIP系列 —— 车辆以太网节点需求汇总

车载诊断协议DoIP系列 —— 车辆以太网节点需求汇总 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师(Wechat:gongkenan2013)。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 本就是小人物,输了就是输了,不要在意别人怎么看自己。江湖一碗茶,…

安装 Windows Server 2003

1.镜像安装 镜像安装:Windows Server 2003 2.安装过程(直接以图的形式呈现) 按Enter(继续),继续后F8继续 直接Enter安装 下一步 秘钥:GM34K-RCRKY-CRY4R-TMCMW-DMDHM 等待安装成功即可

JavaWeb

一、技术栈 【1】 前端部分 HTML CSS JavaScript ES6 Nodejs npm vite vue3 router pinia axios element-plus … 【2】 后端部分 HTTP xml Tomcat Servlet Request Response Cookie Sesssion Filter Listener MySQL JDBC Druid Jackson lombok jwt … 二、JAVAWEB交互模…

【知识整理】产研中心岗位评定标准之大数据岗位

为贯彻执行集团数字化转型的需要,该知识库将公示集团组织内各产研团队不同角色成员的职务“职级”岗位的评定标准; 一、定级定档目的 通过对公司现有岗位及相应岗位员工的工作能力、工作水平进行客观公正评定,确定各岗位的等级及同等级岗位员工对应的档级,从而为员工以后的晋升…

三种输入输出函数

目录 printf函数 scanf函数 getchar函数 putchar函数 gets函数 puts函数 printf函数 当你需要将数据或文本输出到屏幕或其他输出设备时&#xff0c;C语言提供了一个非常有用的函数&#xff0c;即 printf() 函数。它是标准库中定义的函数&#xff0c;用于格式化输出。 pr…

React 的调度系统 Scheduler

原文地址1 原文地址2 其中startTime是任务开始的时间&#xff0c;默认是-1&#xff0c;任务开始时将任务开始时间赋值给了startTime&#xff0c; 这里意思是判断这个任务执行时间是否超过5ms(写死的)。若超过&#xff0c;则要交出。

Linux platform tree下的单总线驱动程序设计(DHT11)

目录 概述 1 认识DHT11 1.1 DHT11特性 1.2 DHT11数据格式 1.3 DHT11与MCU通信 1.4 DHT11信号解析 1.4.1 起始信号 1.4.2 解析信号0 1.4.3 解析信号1 2 驱动开发 2.1 硬件接口 2.2 更新设备树 2.2.1 添加驱动节点 2.2.2 编译.dts 2.2.3 更新板卡中的.dtb 2.3 驱…