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

设计模式之迭代器模式:遍历的艺术与实现

引言

迭代器模式(Iterator Pattern)是一种行为型设计模式,它提供了一种顺序访问聚合对象中各个元素的方法,而又不暴露其底层实现。迭代器模式将遍历逻辑与聚合对象解耦,使得我们可以用统一的方式处理不同的集合结构。本文将深入探讨迭代器模式的原理、实现方式以及实际应用场景,帮助你掌握这种优雅的遍历机制。


1. 迭代器模式的核心概念

1.1 什么是迭代器模式?

迭代器模式是一种行为型设计模式,它通过提供统一的接口来顺序访问聚合对象中的元素,而不需要了解底层数据结构的具体实现。

1.2 迭代器模式的应用场景
  • 统一遍历接口:需要为不同类型的集合提供统一的遍历方式

  • 隐藏集合实现:不希望暴露集合内部结构给客户端

  • 支持多种遍历:需要同时支持多种遍历方式(如前序、中序、后序)


2. 迭代器模式的实现方式

2.1 基本结构

迭代器模式通常包含以下几个角色:

  • 迭代器接口(Iterator):定义遍历集合的接口

  • 具体迭代器(ConcreteIterator):实现迭代器接口

  • 聚合接口(Aggregate):定义创建迭代器的接口

  • 具体聚合类(ConcreteAggregate):实现聚合接口

2.2 代码示例
// 迭代器接口
public interface Iterator<T> {boolean hasNext();T next();
}// 聚合接口
public interface Aggregate<T> {Iterator<T> createIterator();
}// 具体聚合类
public class BookCollection implements Aggregate<String> {private String[] books = {"Design Patterns", "Clean Code", "Refactoring"};@Overridepublic Iterator<String> createIterator() {return new BookIterator();}// 具体迭代器(内部类)private class BookIterator implements Iterator<String> {private int index = 0;@Overridepublic boolean hasNext() {return index < books.length;}@Overridepublic String next() {if (hasNext()) {return books[index++];}throw new NoSuchElementException();}}
}// 客户端代码
public class Client {public static void main(String[] args) {Aggregate<String> collection = new BookCollection();Iterator<String> iterator = collection.createIterator();while (iterator.hasNext()) {System.out.println(iterator.next());}}
}

3. 迭代器模式的最佳实践

3.1 封装遍历逻辑
  • 单一职责:将遍历逻辑从集合类中分离出来

  • 简化集合接口:保持集合接口的简洁性

3.2 支持多种遍历方式
  • 前序/后序遍历:通过不同的迭代器实现

  • 过滤迭代器:实现带过滤条件的遍历

3.3 线程安全考虑
  • 快速失败机制:检测并发修改

  • 不可变迭代器:返回集合的快照


4. 迭代器模式的实际应用

4.1 树形结构遍历
// 二叉树节点
class TreeNode {int value;TreeNode left;TreeNode right;// 中序迭代器public Iterator<Integer> inOrderIterator() {return new InOrderIterator(this);}private static class InOrderIterator implements Iterator<Integer> {private Stack<TreeNode> stack = new Stack<>();public InOrderIterator(TreeNode root) {pushLeft(root);}private void pushLeft(TreeNode node) {while (node != null) {stack.push(node);node = node.left;}}@Overridepublic boolean hasNext() {return !stack.isEmpty();}@Overridepublic Integer next() {TreeNode node = stack.pop();pushLeft(node.right);return node.value;}}
}
4.2 文件系统遍历
// 文件系统迭代器
public class FileSystemIterator implements Iterator<File> {private Queue<File> queue = new LinkedList<>();public FileSystemIterator(File root) {queue.offer(root);}@Overridepublic boolean hasNext() {return !queue.isEmpty();}@Overridepublic File next() {File current = queue.poll();if (current.isDirectory()) {File[] children = current.listFiles();if (children != null) {for (File child : children) {queue.offer(child);}}}return current;}
}
4.3 数据库结果集遍历
// 数据库结果集迭代器
public class ResultSetIterator implements Iterator<Map<String, Object>> {private ResultSet rs;private boolean hasNext;public ResultSetIterator(ResultSet rs) throws SQLException {this.rs = rs;this.hasNext = rs.next();}@Overridepublic boolean hasNext() {return hasNext;}@Overridepublic Map<String, Object> next() {try {Map<String, Object> row = new HashMap<>();ResultSetMetaData meta = rs.getMetaData();for (int i = 1; i <= meta.getColumnCount(); i++) {row.put(meta.getColumnName(i), rs.getObject(i));}hasNext = rs.next();return row;} catch (SQLException e) {throw new RuntimeException(e);}}
}

5. 迭代器模式的优缺点

5.1 优点
  • 解耦集合与遍历逻辑

  • 支持多种遍历方式

  • 简化集合接口

  • 可以暂停遍历过程

5.2 缺点
  • 简单集合可能过度设计

  • 性能开销(某些实现)

  • 可能破坏封装(如果迭代器修改集合)


结语

迭代器模式是处理集合遍历的优雅解决方案,它通过将遍历逻辑抽象出来,使得我们可以用统一的方式处理各种数据结构。掌握迭代器模式不仅能让你写出更清晰的代码,还能更好地理解Java集合框架的设计思想。希望本文能帮助你深入理解这一重要的设计模式!


如果你需要了解特定语言的实现细节或有其他相关问题,欢迎随时提问!

相关文章:

设计模式之迭代器模式:遍历的艺术与实现

引言 迭代器模式&#xff08;Iterator Pattern&#xff09;是一种行为型设计模式&#xff0c;它提供了一种顺序访问聚合对象中各个元素的方法&#xff0c;而又不暴露其底层实现。迭代器模式将遍历逻辑与聚合对象解耦&#xff0c;使得我们可以用统一的方式处理不同的集合结构。…...

红宝书第三十六讲:持续集成(CI)配置入门指南

红宝书第三十六讲&#xff1a;持续集成&#xff08;CI&#xff09;配置入门指南 资料取自《JavaScript高级程序设计&#xff08;第5版&#xff09;》。 查看总目录&#xff1a;红宝书学习大纲 一、什么是持续集成&#xff1f; 持续集成&#xff08;CI&#xff09;就像咖啡厅的…...

Java—HTML:3D形变

今天我要介绍的是在Java HTML中CSS的相关知识点内容之一&#xff1a;3D形变&#xff08;3D变换&#xff09;。该内容包含透视&#xff08;属性&#xff1a;perspective&#xff09;&#xff0c;3D变换&#xff0c;3D变换函数以及案例演示&#xff0c; 接下来我将逐一介绍&…...

什么是音频预加重与去加重,预加重与去加重的原理是什么,在什么条件下会使用预加重与去加重?

音频预加重与去加重是音频处理中的两个重要概念&#xff0c;以下是对其原理及应用条件的详细介绍&#xff1a; 1、音频预加重与去加重的定义 预加重&#xff1a;在音频信号的发送端&#xff0c;对音频信号的高频部分进行提升&#xff0c;增加高频信号的幅度&#xff0c;使其在…...

免费下载 | 2025清华五道口:“十五五”金融规划研究白皮书

《2025清华五道口&#xff1a;“十五五”金融规划研究白皮书》的核心内容主要包括以下几个方面&#xff1a; 一、五年金融规划的重要功能与作用 凝聚共识&#xff1a;五年金融规划是国家金融发展的前瞻性谋划和战略性安排&#xff0c;通过广泛听取社会各界意见&#xff0c;凝…...

微信小程序实战案例 - 餐馆点餐系统 阶段 4 - 订单列表 状态

✅ 阶段 4 – 订单列表 & 状态 目标 展示用户「我的订单」列表支持状态筛选&#xff08;全部 / 待处理 / 已完成&#xff09;支持分页加载和实时刷新使用原生组件编写 ✅ 1. 页面结构&#xff1a;文件结构 pages/orders/├─ index.json├─ index.wxml├─ index.js└─…...

如何为C++实习做准备?

博主介绍&#xff1a;程序喵大人 35- 资深C/C/Rust/Android/iOS客户端开发10年大厂工作经验嵌入式/人工智能/自动驾驶/音视频/游戏开发入门级选手《C20高级编程》《C23高级编程》等多本书籍著译者更多原创精品文章&#xff0c;首发gzh&#xff0c;见文末&#x1f447;&#x1…...

【docker】--部署--安装docker教程

文章目录 环境方法一&#xff1a;脚本安装方法二&#xff1a;手动安装**步骤 1&#xff1a;卸载旧版本&#xff08;如有&#xff09;****步骤 2&#xff1a;更新系统并安装依赖****步骤 3&#xff1a;添加 Docker 官方 GPG 密钥****步骤 4&#xff1a;设置 Docker 仓库****步骤…...

【开发记录】服务外包大赛记录

参加服务外包大赛的A07赛道中&#xff0c;最近因为频繁的DEBUG&#xff0c;心态爆炸 记录错误 以防止再次出现错误浪费时间。。。 2025.4.13 项目在上传图片之后 会自动刷新 没有等待后端返回 Network中的fetch /upload显示canceled. 然而这是使用了VS的live Server插件才这样&…...

Cesium.js(6):Cesium相机系统

Camera表示观察场景的视角。通过操作摄像机&#xff0c;可以控制视图的位置、方向和角度。 帮助文档&#xff1a;Camera - Cesium Documentation 1 setView setView 方法允许你指定相机的目标位置和姿态。你可以通过 Cartesian3 对象来指定目标位置&#xff0c;并通过 orien…...

AI 代码生成工具如何突破 Java 单元测试效能天花板?

一、传统单元测试的四大痛点 时间黑洞&#xff1a;根据 JetBrains 调研&#xff0c;Java 开发者平均花费 35% 时间编写测试代码覆盖盲区&#xff1a;手工测试覆盖率普遍低于 60%&#xff08;Jacoco 全球统计数据&#xff09;维护困境&#xff1a;业务代码变更导致 38% 的测试用…...

AF3 ProteinDataset类的_patch方法解读

AlphaFold3 protein_dataset模块 ProteinDataset 类 _patch 方法的主要目的是围绕锚点残基(anchor residues)裁剪蛋白质数据,提取一个局部补丁(patch)作为模型输入。 源代码: def _patch(self, data):"""Cut the data around the anchor residues."…...

客户端负载均衡与服务器端负载均衡详解

客户端负载均衡与服务器端负载均衡详解 1. 客户端负载均衡&#xff08;Client-Side Load Balancing&#xff09; 核心概念 定义&#xff1a;负载均衡逻辑在客户端实现&#xff0c;客户端主动选择目标服务实例。典型场景&#xff1a;微服务内部调用&#xff08;如Spring Cloud…...

vue-element-plus-admin的安装

文档链接&#xff1a;开始 | vue-element-plus-admin 之前尝试按照官方文档来安装&#xff0c;运行npm run dev命令却不能正常打开访问浏览器&#xff0c;换一个方式 首先在目录下打开命令窗口 1、克隆项目 从 GitHub 获取代码 # clone 代码 git clone https://github.com…...

基于springboot的“流浪动物管理系统”的设计与实现(源码+数据库+文档+PPT)

基于springboot的“流浪动物管理系统”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;springboot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 系统功能结构图 局部E-R图 系统首页界面 系统…...

爬虫解决debbugger之替换文件

鼠鼠上次做一个网站的时候&#xff0c;遇到的debbugger问题&#xff0c;是通过打断点然后编辑断点解决的&#xff0c;现在鼠鼠又学会了一个新的技能 首先需要大家下载一个reres的插件&#xff0c;这里最好用谷歌浏览器 先请大家看看案例国家水质自动综合监管平台 这里我们只…...

奇怪的电梯——DFS算法

题目 题解 每到一层楼都面临了两种选择&#xff1a;上还是下&#xff1f;因此我们可以定义一个布尔数组用来记录选择。 终止条件其实也明显&#xff0c;要么到了B层&#xff0c;要么没有找到楼层。 如果找到了&#xff0c;选择一个步骤少的方式。又怎么表示没有找到楼层&…...

Open GL ES-> 工厂设计模式包装 SurfaceView + 自定义EGL的OpenGL ES 渲染框架

XML文件 <?xml version"1.0" encoding"utf-8"?> <com.example.myapplication.EGLSurfaceView xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"…...

2.4goweb加解密和jwt

MD5的基本实现 1. ​​标准库调用​​ Go语言通过crypto/md5包提供MD5算法的实现。核心步骤包括&#xff1a; ​​创建哈希对象​​&#xff1a;使用md5.New()生成一个实现了hash.Hash接口的实例。​​写入数据​​&#xff1a;通过Write()方法或io.WriteString()将数据写入…...

深入解析多表联查(MySQL)

前言 在面试中以及实际开发中&#xff0c;多表联查是每个程序员必备技能&#xff0c;下文通过最简单的学生表和课程表的实例帮大家最快入门多表联查技能。 建立数据表 1. 学生表&#xff08;students&#xff09; 创建学生表 CREATE TABLE students (student_id INT AUTO_…...

宇视设备视频平台EasyCVR打造智慧酒店安防体系,筑牢安全防线

一、需求背景 酒店作为人员流动频繁的场所&#xff0c;对安全保障与隐私保护有着极高的要求。为切实维护酒店内部公共区域的安全秩序&#xff0c;24小时不间断视频监控成为必要举措。通常情况下&#xff0c;酒店需在本地部署视频监控系统以供查看&#xff0c;部分连锁酒店还希…...

C++ 编程指南36 - 使用Pimpl模式实现稳定的ABI接口

一&#xff1a;概述 C 的类布局&#xff08;尤其是私有成员变量&#xff09;直接影响它的 ABI&#xff08;应用二进制接口&#xff09;。如果你在类中添加或修改了私有成员&#xff0c;即使接口不变&#xff0c;编译器生成的二进制布局也会变&#xff0c;从而导致 ABI 不兼容。…...

Linux中的文件传输(附加详细实验案例)

一、实验环境的设置 ①该实验需要两台主机&#xff0c;虚拟机名称为 L2 和 L3 &#xff0c;在终端分别更改主机名为 node1 和 node2&#xff0c;在实验过程能够更好分辨。 然后再重新打开终端&#xff0c;主机名便都更改了相应的名称。 ②用 ip a 的命令分别查看两个主机的 …...

基于 OpenHarmony 5.0 的星闪轻量型设备应用开发——Ch2 OpenHarmony LiteOS-M 内核应用开发

写在前面&#xff1a; 此篇是系列文章《基于 OpenHarmony5.0 的星闪轻量型设备应用开发》的第 2 章。本篇介绍了如何在 OpenHarmony 5.0 框架下&#xff0c;针对 WS63 进行 LiteOS-M 内核应用工程的开发。 为了方便读者学习&#xff0c;需要OpenHarmony 5.0 WS63 SDK 的小伙伴可…...

论文阅读:2024-arxiv How to Steer LLM Latents for Hallucination Detection?

总目录 大模型安全相关研究:https://blog.csdn.net/WhiffeYF/article/details/142132328 How to Steer LLM Latents for Hallucination Detection? https://arxiv.org/pdf/2503.01917 https://www.doubao.com/chat/2818934852496130 其它资料: https://blog.csdn.net/we…...

Linux--线程概念与控制

目录 1. Linux线程概念 1-1 什么是线程 1-2 分⻚式存储管理 1-2-1 虚拟地址和⻚表的由来 1-2-2 物理内存管理 1-2-3 ⻚表 1-2-4 ⻚⽬录结构 1-2-5 两级⻚表的地址转换 1-2-6 缺⻚异常 1-3 线程的优点 1-4 线程的缺点 1-5 线程异常 1-6 线程⽤途 2. Linux进程VS线…...

Python | kelvin波的水平空间结构

写在前面 简单记录一下之前想画的一个图&#xff1a; 思路 整体比较简单&#xff0c;两个子图&#xff0c;本质上就是一个带有投影&#xff0c;一个不带投影&#xff0c;通常用在EOF的空间模态和时间序列的绘制中&#xff0c;可以看看之前的几个详细的画法。 Python | El Ni…...

【音视频】SDL播放PCM音频

相关API 打开音频设备 int SDLCALL SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained); desired&#xff1a;期望的参数。obtained&#xff1a;实际音频设备的参数&#xff0c;一般情况下设置为NULL即可。 SDL_AudioSpec typedef struct SDL_AudioSpec { i…...

BERT - Bert模型框架复现

本节将实现一个基于Transformer架构的BERT模型。 1. MultiHeadAttention 类 这个类实现了多头自注意力机制&#xff08;Multi-Head Self-Attention&#xff09;&#xff0c;是Transformer架构的核心部分。 在前几篇文章中均有讲解&#xff0c;直接上代码 class MultiHeadAtt…...

【LeetCode 热题100】二叉树遍历入门:从中序遍历到层序与右视图(力扣94 / 102/199)(Go语言版)

&#x1f333; 二叉树遍历入门&#xff1a;从中序遍历到层序与右视图 本文涵盖 LeetCode 上的三道基础但极具代表性的二叉树遍历题&#xff1a; 二叉树的中序遍历 二叉树的层序遍历 二叉树的右视图 通过这些题目&#xff0c;我们将从 DFS 到 BFS&#xff0c;深入理解如何处理…...