java基础 迭代Iterable接口以及迭代器Iterator

Itera迭代

  • Iterable < T>迭代接口
    • (1) Iterator iterator()
    • (2) forEach(Consumer<? super T> action)
      • forEach结合Consumer常见场景
      • forEach使用注意细节
    • (3)Spliterator spliterator()
  • Iterator< T>迭代器接口
    • 如何“接收” Iterator<T>
    • 核心方法
    • 迭代器的使用场景
    • 注意事项
  • 总结

在 Java 中, Iterable < T> 是一个核心接口,用于表示一个对象可以被 迭代(遍历),它定义了如何通过 迭代器(Iterator< T>)访问其元素,并支持增强的 for-each 循环

Iterable < T>迭代接口

public interface Iterable<T> {Iterator<T> iterator(); // 必须实现的方法// Java 8 新增的默认方法default void forEach(Consumer<? super T> action) { /* ... */ }// Java 8 新增的默认方法default Spliterator<T> spliterator() { /* ... */ }
}

(1) Iterator iterator()

作用:返回一个迭代器(Iterator< T>),用于遍历集合中的元素或进行删除元素操作。
实现要求:每个 Iterable 实现类必须提供该方法,返回一个新的迭代器实例

(2) forEach(Consumer<? super T> action)

作用:对集合中的每个非空元素进行遍历

	// 下界通配符 <? super T> 表示“T 或 T 的父类”default void forEach(Consumer<? super T> action) {Objects.requireNonNull(action);for (T t : this) {action.accept(t);}}

首先,这段代码里的forEach方法接受一个Consumer(消费者)参数,Consumer是一个函数式接口,接受一个输入参数并且不返回结果,accept方法为void
其次,这里用了泛型通配符<? super T>,表示Consumer可以处理T类型及其父类,比如有一个Animal的Consumer,而T是Dog,那么也可以接受这个Consumer。

步骤1.首先Objects.requireNonNull,确保传入的action不是null,避免空指针异常,注意是action判空
步骤2.接下来是一个增强的for循环,遍历this,也就是当前的Iterable实例
步骤3.每次循环取出元素t,调用action的accept方法处理它,具体如何处理 t,完全由 Consumer 的实现逻辑决定,是具体的消费操作action

forEach结合Consumer常见场景

(1) 示例 1:打印元素

List<String> list = Arrays.asList("A", "B", "C");
list.forEach(element -> System.out.println(element));

forEach方法参数是 str -> System.out.println(str) :是一个 Consumer< String> 的实现,action就是打印元素:每次调用 accept(t) 时,会执行 System.out.println(t),即打印当前元素。

(2) 示例 2:修改对象状态

List<Person> persons = getPersons();
persons.forEach(person -> person.setAge(18)); // 将所有 Person 的年龄设为 18

逻辑分解:
person -> person.setAge(18) 是 Consumer 的实现。每次调用 accept(t) 时,执行 t.setAge(18),修改元素的状态。

(3) 示例 3:条件判断与过滤

List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
numbers.forEach(num -> {if (num % 2 == 0) {System.out.println(num + " 是偶数");}
});

在 accept(t) 中,根据 t 的值执行条件判断,仅处理满足条件的元素。

(4) 示例 4:方法引用

list.forEach(System.out::println); // 方法引用

等价于:

list.forEach(str -> System.out.println(str));

原理:System.out::println 是 Consumer< String> 的实现,accept(t) 会调用 System.out.println(t)

forEach使用注意细节

①上述的判空处理是判断集合是否或操作是否为空,不是判断集合中的某个元素为null
②对于Null的元素,foreach遍历输出要看具体的子类处理,如List的遍历是将其作为 null字符打印处理

        List<String> list = Arrays.asList("A",null, "C");list.forEach(element -> System.out.println(element));

输出

A
null //字符null 不是空 Null
C

(3)Spliterator spliterator()

Spliterator可拆分迭代器介绍链接
流Stream AP介绍点击链接
Spliterator 是 Stream API 并行处理的底层实现,现在的实际工作场景中,应用流对集合进行处理是 非常常见的,代码使用是非常简洁的,这两个单独拿出来说

Iterator< T>迭代器接口

Iterator 是 Java 集合框架中用于遍历集合元素的接口,定义如下:

public interface Iterator<T> {boolean hasNext();    // 检查是否还有下一个元素T next();             // 返回下一个元素void remove();        // 移除当前元素(可选操作)
}

如何“接收” Iterator

(1) 通过集合的 iterator() 方法
有实现了 Iterable 接口的集合类(如 List, Set, Queue)都可通过 iterator() 方法返回迭代器:

List<String> list = Arrays.asList("A", "B", "C");
Iterator<String> iterator = list.iterator(); // 获取迭代器

(2) 自定义集合类实现 Iterable<T>
若需让自定义集合支持迭代,需实现 Iterable 并返回自定义的 Iterator

public class MyCollection<T> implements Iterable<T> {private List<T> elements = new ArrayList<>();public void add(T element) {elements.add(element);}@Overridepublic Iterator<T> iterator() {return new MyIterator(); // 返回自定义迭代器}// 自定义迭代器实现private class MyIterator implements Iterator<T> {private int index = 0;@Overridepublic boolean hasNext() {return index < elements.size();}@Overridepublic T next() {if (!hasNext()) throw new NoSuchElementException();return elements.get(index++);}@Overridepublic void remove() {elements.remove(--index);}}
}

核心方法

(1) boolean hasNext()
作用:判断集合中是否还有未被遍历的元素。
返回值:
true:存在下一个元素。
false:已遍历完所有元素。

List<String> list = Arrays.asList("A", "B", "C");
Iterator<String> it = list.iterator();
while (it.hasNext()) { // 检查是否还有元素String element = it.next();System.out.println(element);
}

(2) T next()
作用:返回当前指向的元素,并将迭代器位置后移。
注意事项:
调用前必须检查 hasNext(),否则可能抛出 NoSuchElementException
返回类型为泛型 T,确保类型安全

Iterator<Integer> it = List.of(1, 2, 3).iterator();
if (it.hasNext()) {int num = it.next(); // 返回 1,迭代器指向下一个元素
}

(3) void remove()
作用:移除迭代器最后一次通过 next() 返回的元素。
注意事项:
必须在 next() 之后调用,否则抛出 IllegalStateException
不是所有迭代器都支持此操作,如ArrayList的迭代器执行此操作,不支持删除操作的迭代器如Collections.unmodifiableList()返回的迭代器,调用前需检查是否实现(默认可能抛出 UnsupportedOperationException)。

List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));
Iterator<String> it = list.iterator();
while (it.hasNext()) {String element = it.next();if (element.equals("B")) {it.remove(); // 移除 "B"}
}
System.out.println(list); // 输出 [A, C]

(4) forEachRemaining(Consumer<? super E> action)
上面三个方法是迭代器的核心方法,这个方法是将上面三个方法集合在一起了,他是对父接口的for-each方法的一种补充

    default void forEachRemaining(Consumer<? super E> action) {Objects.requireNonNull(action);while (hasNext())action.accept(next());}

和for-each区别就在于,for-each会将集合中的全部元素按照执行操作执行一遍,forEachRemaining则是将剩余未处理的元素按照执行操作执行一遍,配合可拆分迭代器spliterator中使用样例

List<String> list = Arrays.asList("Java", "Python", "C++", "Go");
Spliterator<String> spliterator = list.spliterator();// 处理前两个元素
spliterator.tryAdvance(System.out::println); // Java
spliterator.tryAdvance(System.out::println); // Python// 这时候还剩余两个元素 批量处理剩余元素 
spliterator.forEachRemaining(System.out::println); // 输出:
// C++
// Go

迭代器的使用场景

(1) 遍历集合并修改元素

List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3));
Iterator<Integer> it = numbers.iterator();
while (it.hasNext()) {int num = it.next();if (num % 2 == 0) {it.remove(); // 安全删除偶数}
}

(2) 遍历不可索引的集合(如 Set)

Set<String> names = new HashSet<>(Set.of("Alice", "Bob"));
Iterator<String> it = names.iterator();
while (it.hasNext()) {System.out.println(it.next());
}

(3) 结合流式处理(Stream API)
这种方式也是实际工作中常见的

List<String> list = List.of("Java", "Python", "C++");
list.stream().filter(s -> s.startsWith("J")).forEach(System.out::println); // 输出 "Java"

注意事项

①迭代器的三个方法执行有先后顺序
boolean hasNext(); // 检查是否还有下一个元素
T next(); // 返回下一个元素
void remove(); // 移除当前元素(可选操作)
hasNext() 先保证还有下一个元素 ===》next()指针才做指向下一个元素返回---》指向返回元素才能进行操作元素 remove();删除

②单次遍历:一个迭代器只能遍历集合一次,遍历结束后需重新获取迭代器。不可重复使用迭代器 即每次调用 iterator() 应返回一个新的迭代器实例。

③并发修改

List<String> list = new ArrayList<>(Arrays.asList("A", "B"));
Iterator<String> it = list.iterator();
list.add("C"); // 直接修改集合
it.next();     // 抛出 ConcurrentModificationException

解决方案:使用并发集合(如 CopyOnWriteArrayList)或在迭代期间仅通过迭代器修改集合

总结

1.迭代Iterable接口和迭代器Iterator接口 联系与区别
①关联:Iterable接口主要生成迭代器和增强for each循环,而增强的 for-each 循环底层依赖 Iterator,无论是在集合还是数组上使用 for-each 循环,其内部都会转换为相应的迭代器操作,具体的实现方式需要去查看迭代接口的实现类,如ArrayList

//增强for each循环
for (String s : list) {System.out.println(s);
}
//等价于:
Iterator<String> it = list.iterator();
while (it.hasNext()) {String s = it.next();System.out.println(s);
}

②区别:除此之外迭代器提供了一种更为安全的删除元素的操作方式,即迭代器的三个关键方法:hasNext(), next(), remove()配合使用,当仅仅需要遍历集合使用for-each就可以,但如果需要删除元素时,可以使用迭代器的 remove() 方法,两者的主要区别

Iterable<T>Iterator<T>
表示对象可被迭代实际执行迭代操作
定义 iterator() 方法定义 hasNext(), next(), remove()
支持 for-each 循环手动控制遍历过程

2.集合框架中几乎所有集合类都实现了 Iterable,例如

  • List(如 ArrayList, LinkedList)
  • Set(如 HashSet, TreeSet)
  • Queue(如 PriorityQueue)

表名这些集合类都是可以被迭代的,当然也都都可以使用迭代器

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

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

相关文章

PyTorch构建自定义模型

PyTorch 提供了灵活的方式来构建自定义神经网络模型。下面我将详细介绍从基础到高级的自定义模型构建方法&#xff0c;包含实际代码示例和最佳实践。 一、基础模型构建 1. 继承 nn.Module 基类 所有自定义模型都应该继承 torch.nn.Module 类&#xff0c;并实现两个基本方法&…

AI智算-K8s如何利用GPFS分布式并行文件存储加速训练or推理

文章目录 GPFS简介核心特性存储环境介绍存储软件版本客户端存储RoCEGPFS 管理(GUI)1. 创建 CSI 用户2. 检查GUI与k8s通信文件系统配置1. 开启配额2. 启用filesetdf文件系统3. 验证文件系统配置4. 启用自动inode扩展存储集群配置1. 启用对根文件集(root fileset)配额2. igno…

gbase8s之逻辑导出导入脚本(完美版本)

该脚本dbexport.sh用于快速导出库和导入库&#xff08;使用多并发unload&#xff0c;和多并发dbload的方式&#xff09; #!/bin/sh #脚本功能&#xff1a;将数据导出成文本&#xff0c;迁移至其他实例 #最后更新时间&#xff1a;2023-12-19 #使用方法&#xff1a; #1.执行该脚…

springMVC-拦截器详解

拦截器 概述 SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。开发者可以自己定义一些拦截器来实现特定的功能。 过滤器与拦截器的区别&#xff1a;拦截器是AOP思想的具体应用。 过滤器 servlet规范中的一部分&#xff0c;任何ja…

网络安全应急响应-系统排查

在网络安全应急响应中&#xff0c;系统排查是快速识别潜在威胁的关键步骤。以下是针对Windows和Linux系统的系统基本信息排查指南&#xff0c;涵盖常用命令及注意事项&#xff1a; 一、Windows系统排查 1. 系统信息工具&#xff08;msinfo32.exe&#xff09; 命令执行&#x…

基于YOLO的半自动化标注方法:提升铁路视频缺陷检测效率

论文地址:https://arxiv.org/pdf/2504.01010 1. 论文结构概述 本文提出了一种半自动化标注方法,旨在解决铁路缺陷检测中大规模图像/视频数据集标注成本高、耗时长的问题。论文结构清晰,分为以下核心部分: ​引言(Introduction)​ 强调传统手动标注的痛点(耗时、易错、…

Linux驱动开发:SPI驱动开发原理

前言 本文章是根据韦东山老师的教学视频整理的学习笔记https://video.100ask.net/page/1712503 SPI 通信协议采用同步全双工传输机制&#xff0c;拓扑架构支持一主多从连接模式&#xff0c;这种模式在实际应用场景中颇为高效。其有效传输距离大致为 10m &#xff0c;传输速率…

Android Hilt 教程

Android Hilt 教程 —— 一看就懂&#xff0c;一学就会 1. 什么是 Hilt&#xff1f;为什么要用 Hilt&#xff1f; Hilt 是 Android 官方推荐的 依赖注入&#xff08;DI&#xff09;框架&#xff0c;基于 Dagger 开发&#xff0c;能够大大简化依赖注入的使用。 为什么要用 Hi…

【算法手记11】NC41 最长无重复子数组 NC379 重排字符串

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:刷题 ⚙️操作环境:牛客网 目录 一.NC41 最长无重复子数组 题目详情: 题目思路: 解题代码: 二.NC379 重排字符串 题目详情: 题目思路: 解题代码: 结语 一.NC41 最长无重复子数组 牛客网题目链接(点击即可跳转):NC41 最长…

C语言:字符串处理函数strstr分析

在 C 语言中&#xff0c;strstr 函数用于查找一个字符串中是否存在另一个字符串。它的主要功能是搜索指定的子字符串&#xff0c;并返回该子字符串在目标字符串中第一次出现的位置的指针。如果没有找到子字符串&#xff0c;则返回 NULL。 详细说明&#xff1a; 头文件&#xf…

在windows下安装spark

在windows下安装spark完成 安装过程&#xff1a;

MongoDB常见面试题总结(上)

MongoDB 基础 MongoDB 是什么&#xff1f; MongoDB 是一个基于 分布式文件存储 的开源 NoSQL 数据库系统&#xff0c;由 C 编写的。MongoDB 提供了 面向文档 的存储方式&#xff0c;操作起来比较简单和容易&#xff0c;支持“无模式”的数据建模&#xff0c;可以存储比较复杂…

【Java设计模式】第2章 UML急速入门

2-1 本章导航 UML类图与时序图入门 UML定义 统一建模语言(Unified Modeling Language):第三代非专利建模语言。特点:开放方法,支持可视化构建面向对象系统,涵盖模型、流程、代码等。UML分类(2.2版本) 结构式图形:系统静态建模(类图、对象图、包图)。行为式图形:事…

【4】搭建k8s集群系列(二进制部署)之安装master节点组件(kube-apiserver)

一、下载k8s二进制文件 下载地址&#xff1a; https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG -1.20.md 注&#xff1a;打开链接你会发现里面有很多包&#xff0c;下载一个 server 包就够了&#xff0c;包含了 Master 和 Worker Node 二进制文件。…

电子电气架构 --- AUTOSAR 的信息安全架构

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 周末洗了一个澡,换了一身衣服,出了门却不知道去哪儿,不知道去找谁,漫无目的走着,大概这就是成年人最深的孤独吧! 旧人不知我近况,新人不知我过…

ROS2与OpenAI Gym集成指南:从安装到自定义环境与强化学习训练

1.理解 ROS2 和 OpenAI Gym 的基本概念 ROS2&#xff08;Robot Operating System 2&#xff09;&#xff1a;是一个用于机器人软件开发的框架。它提供了一系列的工具、库和通信机制&#xff0c;方便开发者构建复杂的机器人应用程序。例如&#xff0c;ROS2 可以处理机器人不同组…

【设计模式】创建型 -- 单例模式 (c++实现)

文章目录 单例模式使用场景c实现静态局部变量饿汉式&#xff08;线程安全&#xff09;懒汉式&#xff08;线程安全&#xff09;懒汉式&#xff08;线程安全&#xff09; 智能指针懒汉式(线程安全)智能指针call_once懒汉式(线程安全)智能指针call_onceCRTP 单例模式 单例模式是…

C语言之九九乘法表

一、代码展示 二、运行结果 三、代码分析 首先->是外层循环是小于等于9的 然后->是内层循环是小于等于外层循环的 最后->就是\n让九九乘法表的格式更加美观(当然 电脑不同 有可能%2d 也有可能%3d) 四、与以下素数题目逻辑相似 五、运行结果

自动化备份全网服务器数据平台

自动化备份全网服务器数据平台 项目背景知识 总体需求 某企业里有一台Web服务器&#xff0c;里面的数据很重要&#xff0c;但是如果硬盘坏了数据就会丢失&#xff0c;现在领导要求把数据做备份&#xff0c;这样Web服务器数据丢失在可以进行恢复。要求如下&#xff1a;1.每天0…

stm32+esp8266+机智云手机app

现在很多大学嵌入式毕设都要求云端控制&#xff0c;本文章就教一下大家如何使用esp8266去连接机智云的app去进行显示stm32的外设传感器数据啊&#xff0c;控制一些外设啊等。 因为本文章主要教大家如何移植机智云的代码到自己的工程&#xff0c;所以前面的一些准备工作&#x…