当前位置: 首页 > article >正文

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)

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

相关文章:

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>核心方法迭代器的…...

CentOS禁用nouveau驱动

1、验证 nouveau 是否在运行 lsmod | grep nouveau如果命令返回结果&#xff0c;说明 nouveau 驱动正在运行。 2、编辑黑名单文件 通过编辑黑名单配置文件来禁用 nouveau 驱动&#xff0c;这样在系统启动时不会加载它。 vi /etc/modprobe.d/blacklist-nouveau.conf修改以下…...

Linux 时间同步工具 Chrony 简介与使用

一、Chrony 是什么&#xff1f; chrony 是一个开源的网络时间同步工具&#xff0c;主要由两个组件组成&#xff1a; chronyd&#xff1a;后台服务进程&#xff0c;负责与时间服务器交互&#xff0c;同步系统时钟。chronyc&#xff1a;命令行工具&#xff0c;用于手动查看或修…...

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

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

28--当路由器开始“宫斗“:设备控制面安全配置全解

当路由器开始"宫斗"&#xff1a;设备控制面安全配置全解 引言&#xff1a;路由器的"大脑保卫战" 如果把网络世界比作一座繁忙的城市&#xff0c;那么路由器就是路口执勤的交通警察。而控制面&#xff08;Control Plane&#xff09;就是警察的大脑&#xf…...

Vue知识点(5)-- 动画

CSS 动画是 Vue3 中实现组件动画效果的高效方式&#xff0c;主要通过 CSS transitions 和 keyframes 动画 CSS Keyframes&#xff08;关键帧动画&#xff09; 用来创建复杂的动画序列&#xff0c;可以精确控制动画的各个阶段。 核心语法&#xff1a; keyframes animationNa…...

MATLAB2024a超详细图文安装教程(2025最新版保姆级教程)附安装钥

目录 前言 一、MATLAB下载 二、MATLAB安装 二、MATLAB启动 前言 MATLAB&#xff08;Matrix Laboratory&#xff09;是由MathWorks公司开发的一款高性能的编程语言和交互式环境&#xff0c;主要用于数值计算、数据分析和算法开发。内置数学函数和工具箱丰富&#xff0c;开发…...

基于 Spring Boot 瑞吉外卖系统开发(二)

基于 Spring Boot 瑞吉外卖系统开发&#xff08;二&#xff09; 员工登录功能实现 员工登录页面login.html存放在/resources/backend/page/login目录下。 启动项目&#xff0c;在浏览器中通过地址“http://localhost:8080/backend/page/login/login.html”访问员工登录页面。…...

软考系统架构设计师之大数据与人工智能笔记

一、大数据架构设计 1. 核心概念与挑战 大数据特征&#xff1a;体量大&#xff08;Volume&#xff09;、多样性&#xff08;Variety&#xff09;、高速性&#xff08;Velocity&#xff09;、价值密度低&#xff08;Value&#xff09;。传统数据库问题&#xff1a;数据过载、性…...

146. LRU 缓存 带TTL的LRU缓存实现(拓展)

LRU缓存 方法一:手动实现双向链表 哈希表 struct Node{int val;int key;Node* prev;Node* next;Node(int a, int b): key(a), val(b), prev(nullptr), next(nullptr) {}Node():key(0), val(0), prev(nullptr), next(nullptr) {} }; class LRUCache { private:Node* removeTai…...

浅层神经网络:全面解析(扩展)

浅层神经网络&#xff1a;全面解析&#xff08;扩展&#xff09; 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;可以分享一下给大家。点击跳转到网站。 https://www.captainbed.cn/ccc 一、神经网络架构演进图谱 #mermaid-svg-…...

Python监控网站更新则推送到企业微信

import requests from lxml import etree import redis r redis.Redis(host"localhost", port6379, db0)def get_page_content(url):# 获取指定网页中的标题和链接url_lists []headers {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)…...

下一代智能爬虫框架:ScrapeGraphAI 详解

更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、ScrapeGraphAI 概述1.1 ScrapeGraphAI介绍1.2 核心特点1.3 工作流程1.4 关键模块1.5 对比传统爬虫框架1.6 安装二、基础操作2.1 自定义解析规则2.2 数据后处理2.3 分布式爬取三、高级功能3.1 多步骤交互采集3.2 动态…...

Dubbo(30)如何配置Dubbo的服务分片?

配置Dubbo的服务分片&#xff08;也称为服务分组&#xff09;可以帮助你将不同的服务实例分组&#xff0c;以实现隔离和管理。通过服务分片&#xff0c;可以在同一个注册中心中注册多个相同接口的服务&#xff0c;但它们属于不同的分组&#xff0c;消费者可以根据需要选择特定分…...

Qt 事件系统负载测试:深入理解 Qt 事件处理机制

Qt 事件系统负载测试&#xff1a;深入理解 Qt 事件处理机制 文章目录 Qt 事件系统负载测试&#xff1a;深入理解 Qt 事件处理机制摘要引言实现原理1. 自定义事件类型2. 事件队列管理3. 性能指标监控4. 事件发送机制 性能监控实现1. 负载计算2. 内存监控3. 延迟计算 使用效果优化…...

Unity3D仿星露谷物语开发33之光标位置可视化

1、目标 当从道具栏中拖出一个道具到地面的时候&#xff0c;光标区域会显示是否可放置物体的可视化显示。绿色表示可以放置物体&#xff0c;红色表示不可以放置物体。 2、优化InventoryManager脚本 添加2个方法&#xff1a; /// <summary>/// Returns the itemDetails&…...

蓝桥杯冲刺题单--二分

二分 知识点 二分&#xff1a; 1.序列二分&#xff1a;在序列中查找&#xff08;不怎么考&#xff0c;会比较难&#xff1f;&#xff09; 序列二分应用的序列必须是递增或递减&#xff0c;但可以非严格 只要r是mid-1&#xff0c;就对应mid&#xff08;lr1&#xff09;/2 2.答…...

《深度探秘:SQL助力经典Apriori算法实现》

在数据的广袤世界里&#xff0c;隐藏着无数有价值的信息&#xff0c;等待着我们去挖掘和发现。关联规则挖掘算法&#xff0c;作为数据挖掘领域的关键技术&#xff0c;能够从海量数据中找出事物之间潜在的关联关系&#xff0c;为商业决策、学术研究等诸多领域提供有力支撑。其中…...

MySQL原理(一)

目录 一、理解MySQL的服务器与客户端关系 1&#xff1a;MySQL服务器与客户端 2&#xff1a;服务器处理客户端请求 3&#xff1a;常见的存储引擎 二、字符集和比较规则 1&#xff1a;字符集和比较规则简介 2&#xff1a;字符集和比较规则应用 3&#xff1a;乱码原因&…...

Docker+Jenkins+Gitee自动化项目部署

前置条件 docker安装成功 按照下面配置加速 sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-EOF {"registry-mirrors": ["https://register.librax.org"] } EOF sudo systemctl daemon-reload sudo systemctl restart docker一、…...

Nginx 499 错误的原因及解决方法

Nginx 499 错误的原因及解决方法 原因 客户端超时&#xff1a; 客户端在等待服务器响应时超时&#xff0c;导致连接被关闭。 解决方法&#xff1a;优化服务端响应时间&#xff0c;或调大客户端的连接超时时间。 服务端响应过慢&#xff1a; 后端服务处理请求时间过长。 解决方法…...

Linux网络多进程并发服务器和多线程并发服务器

多进程 还是以大小写转换为例子 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <pthread.h> #include <sys/socket.h> #include <arpa/inet.h> #include "wrap.h" #include…...

VScode 画时序图(FPGA)

1、先安装插件&#xff1a; 2、然后就可以编写一个.js文件&#xff0c;如下&#xff1a; {signal: [{name: clk, wave: p.......|..},{name: rstn, wave: 01......|..},{name: din_vld, wave: 0.1.0...|..},{name: din, wave: "x.x...|..", data: ["D0", …...

Kubernetes 集群搭建(二):搭建k8s集群 (1.28版本)

&#xff08;一&#xff09;虚拟环境准备 名称ip备注m1192.168.101.131mastern1192.168.101.132workern2192.168.101.133worker &#xff08;二&#xff09;所有主机统一配置 2.1 关闭防火墙和selinux systemctl stop firewalld systemctl disable firewalld sed -i s/enfo…...

一文详解OpenCV环境搭建:Windows使用CLion配置OpenCV开发环境

在计算机视觉和图像处理领域&#xff0c;OpenCV 是一个不可或缺的工具。其为开发者提供了一系列广泛的算法和实用工具&#xff0c;支持多种编程语言&#xff0c;并且可以在多个平台上运行。对于希望在其项目中集成先进视觉功能的开发者来说&#xff0c;掌握如何配置和使用OpenC…...

Python爬取数据(二)

一.example2包下的 1.re模块的compile函数使用 import repatternre.compile(r\d) print(pattern) 2.match的方法使用 import re patternre.compile(r\d) # m1pattern.match(one123twothree345four) #参数2&#xff1a;指定起始位置(包含),参数3&#xff1a;终止位置(包含),…...

前端用用jsonp的方式解决跨域问题

前端用用jsonp的方式解决跨域问题 前端用用jsonp的方式解决跨域问题 前端用用jsonp的方式解决跨域问题限制与缺点&#xff1a;前端后端测试使用示例 限制与缺点&#xff1a; 不安全、只能使用get方式、后台需要相应jsonp方式的传参 前端 function jsonp(obj) {// 动态生成唯…...

计算机网络 3-2 数据链路层(流量控制与可靠传输机制)

3.4 流量控制与可靠传输机制 流量控制&#xff1a;指由接收方控制发送方的发送速率&#xff0c;使接收方有足够的缓冲空间来接收每个帧 滑动窗口流量控制:一种更高效的流量控制方法。 在任意时刻&#xff0c;发送方都维持一组连续的允许发送帧的序号&#xff0c;称为发送窗口…...

科普:原始数据是特征向量么?

一、输入向量 x \mathbf{x} x是特征向量 机器学习算法公式中的输入向量 x \mathbf{x} x通常要求是特征向量。原因如下&#xff1a; 从算法原理角度&#xff1a;机器学习算法旨在通过对输入数据的学习来建立模型&#xff0c;以实现对未知数据的预测或分类等任务。特征向量是对…...

Jenkins配置的JDK,Maven和Git

1. 前置 在配置前&#xff0c;我们需要先把JDK&#xff0c;Maven和Git安装到Jenkins的服务器上。 &#xff08;1&#xff09;需要进入容器内部&#xff0c;执行命令&#xff1a;docker exec -u root -it 容器号/容器名称&#xff08;2选1&#xff09; bash -- 容器名称 dock…...