迭代器模式(统一对集合的访问方式)

news/2024/5/15 4:54:10

目录

前言

UML

plantuml

类图

实战代码

Iterator

ArrayList

Client

自定义迭代器

TreeNode

TreeUtils

Client


前言

在实际开发过程中,常用各种集合来存储业务数据并处理,比如使用 List,Map,Set 等等集合来存储业务数据。存储在集合中的数据,往往需要遍历集合元素再进行相应的业务处理。

不同的集合类型有不同的数据结构,遍历的方式也各不相同。

而迭代器模式,就是用来简化这项工作,让开发者不必关心底层的数据结构是如何组织的,只需关注如何取用数据。它解决了数据的获取与表示之间的耦合问题,提升了集合管理的灵活性与可维护性。

UML

plantuml

@startuml
'https://plantuml.com/class-diagraminterface Iterator {+ hasNext() : boolean+ next() : type
}class ConcreteIterator {+ hasNext() : boolean+ next() : type
}class Client {+ iterator() : Iterator
}Iterator <|.. ConcreteIteratorClient ..> Iterator@enduml

类图

实战代码

Iterator

JDK 提供了 Iterator 这个顶级接口,JDK 下的集合都实现了 Iterator 接口,这样在遍历集合时,便可以直接使用 iterator 来遍历集合元素,而不用关心底层的数据结构。

ArrayList

以 ArrayList 为例,内部类 Itr 实现了 Iterator 接口,iterator 方法则实例化一个迭代器返回

Client

public class Client {  public static void main(String[] args) {  List<Integer> array = Arrays.asList(1, 2, 3, 4, 5);  Iterator<Integer> iterator = array .iterator();  while (iterator.hasNext()) {  System.out.println(iterator.next());  }  }  
}

自定义迭代器

如果 JDK 的集合类不满足业务需求,则需要自定义集合类,那么就需要自己实现 Iterator 接口,从而让自定义集合也能用统一的方式来遍历集合元素

以实际业务中最常见的分类树来举例,自定义 TreeNode 类,并实现 Iterator 接口

TreeNode

public class TreeNode {String id;String pid;String value;List<TreeNode> children;public String getId() {return id;}public void setId(String id) {this.id = id;}public String getPid() {return pid;}public void setPid(String pid) {this.pid = pid;}public String getValue() {return value;}public void setValue(String value) {this.value = value;}public List<TreeNode> getChildren() {return children;}public void setChildren(List<TreeNode> children) {this.children = children;}public Iterator<TreeNode> iterator() {return new TreeNode.Itr(this);}private class Itr implements Iterator<TreeNode> {TreeNode currentNode;private Deque<TreeNode> stack;public Itr(TreeNode root) {currentNode = root;stack = new LinkedList<>();stack.push(root);}@Overridepublic boolean hasNext() {return !stack.isEmpty();}@Overridepublic TreeNode next() {if (!hasNext()) {throw new NoSuchElementException("No more elements to iterate.");}TreeNode node = stack.pop();currentNode = node;List<TreeNode> children = node.getChildren();if (children != null) {for (int index = children.size() - 1; index >= 0; index--) {stack.push(children.get(index));}}return currentNode;}}
}

TreeUtils

public class TreeUtils {public final static String ROOT = "root";/*** 递归构造树** @param sources 按parentId分类的节点* @param parentId 父id,根节点父id为null* @param getId 获取id* @param setChildren 设置子节点* @return 根节点集合* @param <T> 节点类* @param <R> id类型*/public static <T, R> List<T> buildTree(Map<R, List<T>> sources, R parentId,Function<T, R> getId, BiConsumer<T, List<T>> setChildren) {List<T> nodes = sources.getOrDefault(parentId, emptyList());for (T node : nodes) {List<T> subNodes = buildTree(sources, getId.apply(node), getId, setChildren);setChildren.accept(node, subNodes);}return nodes;}}

Client

public class Client {public static void main(String[] args) {TreeNode root = new TreeNode();root.setId("1");root.setPid(null);root.setValue("root");TreeNode child1 = new TreeNode();child1.setId("2");child1.setPid("1");child1.setValue("child1");TreeNode child2 = new TreeNode();child2.setId("3");child2.setPid("1");child2.setValue("child2");TreeNode child3 = new TreeNode();child3.setId("4");child3.setPid("2");child3.setValue("child3");//模拟从数据库中查到的节点数据List<TreeNode> nodes = Arrays.asList(root, child1, child2, child3);//按父节点分类Map<String, List<TreeNode>> sources = nodes.stream().collect(groupingBy(e -> Objects.isNull(e.getPid()) ? ROOT : e.getPid()));//构造树List<TreeNode> tree = TreeUtils.buildTree(sources, ROOT, TreeNode::getId, TreeNode::setChildren);for (TreeNode node : tree) {Iterator iterator = node.iterator();while (iterator.hasNext()) {TreeNode child = (TreeNode) iterator.next();System.out.println(child.getId() + " " + child.getValue());}}}
}

http://www.mrgr.cn/p/58284642

相关文章

苹果应用退款登录链接

https://reportaproblem.apple.com/物书堂app退出中国区苹果应用商店 https://forum.freemdict.com/t/topic/16708/4

React组件封装:文字、表情评论框

1.需求描述 根据项目需求,采用Antd组件库需要封装一个评论框,具有以下功能:支持文字输入 支持常用表情包选择 支持发布评论 支持自定义表情包2.封装代码./InputComment.tsx1 import React, { useState, useRef, useEffect, forwardRef, useImperativeHandle } from react;2 …

[转帖]软件出口管制中的相关法律问题和分析

https://www.sohu.com/a/294379160_221481 作者|方春晖 刘良勇 宋献涛 北京德和衡律师事务所 (本文系知产力获得独家首发的稿件,转载须征得作者本人同意,并在显要位置注明文章来源。) (本文8010字,阅读约需16分钟) 序 言 在国际贸易争端进程中,出口管制合规方面的话题不…

Switch 和 PS1 模拟器:3000+ 游戏随心玩 | 开源日报 No.174

Ryujinx/Ryujinx Stars: 26.1k License: MIT Ryujinx 是用 C# 编写的实验性任天堂 Switch 模拟器。 该项目旨在提供出色的准确性和性能、用户友好的界面以及稳定的构建。它已经通过了大约 4050 个测试&#xff0c;其中超过 4000 个可以启动并进入游戏&#xff0c;其中大约 340…

分类模型评估:混淆矩阵与ROC曲线

1.混淆矩阵2.ROC曲线 & AUC指标 理解混淆矩阵和ROC曲线之前&#xff0c;先区分几个概念。对于分类问题&#xff0c;不论是多分类还是二分类&#xff0c;对于某个关注类来说&#xff0c;都可以看成是二分类问题&#xff0c;当前的这个关注类为正类&#xff0c;所有其他非关注…

LineageOS刷机教程

一、刷机准备工作 在 https://download.lineageos.org.cn/ 这个网址里找到自己的手机型号,也可以用Ctrl+F搜索手机型号关键字找到后点击下载下载页面左侧找到自己的手机型号(不知道上面点击下载,进来的二级页面还得再找一次)下载好lineageOS的刷机包,boot.img文件,recove…

Linux基础篇:解析Linux命令执行的基本原理

Linux 命令是一组可在 Linux 操作系统中使用的指令&#xff0c;用于执行特定的任务&#xff0c;例如管理文件和目录、安装和配置软件、网络管理等。这些命令通常在终端或控制台中输入&#xff0c;并以文本形式显示输出结果。 Linux 命令通常以一个或多个单词的简短缩写或单词…

C++王牌结构hash:哈希表闭散列的实现与应用

一、哈希概念 顺序结构以及平衡树中&#xff0c;元素关键码与其存储位置之间没有对应的关系&#xff0c;因此在查找一个元素 时&#xff0c;必须要经过关键码的多次比较。顺序查找时间复杂度为O(N)&#xff0c;平衡树中为树的高度&#xff0c;即O(log n)&#xff0c;搜索的效率…

Unity AI Navigation自动寻路

目录 前言一、Unity中AI Navigation是什么&#xff1f;二、使用步骤1.安装AI Navigation2.创建模型和材质3.编写向目标移动的脚本4.NavMeshLink桥接组件5.NavMeshObstacle组件6.NavMeshModifler组件 三、效果总结 前言 Unity是一款强大的游戏开发引擎&#xff0c;而人工智能&a…

TCP三次握手、四次挥手出现意外情况时,如何保证稳定可靠?

TCP 作为一个靠谱的协议,在传输数据的前后,需要在双端之间建立连接,并在双端各自维护连接的状态。TCP 并没有什么特别之处,在面对多变的网络情况,也只能通过不断的重传和各种算法来保证可靠性。建立连接前,TCP 会通过三次握手来保证双端状态正确,然后就可以正常传输数据…

八大技术趋势案例(人工智能物联网)

科技巨变,未来已来,八大技术趋势引领数字化时代。信息技术的迅猛发展,深刻改变了我们的生活、工作和生产方式。人工智能、物联网、云计算、大数据、虚拟现实、增强现实、区块链、量子计算等新兴技术在各行各业得到广泛应用,为各个领域带来了新的活力和变革。 为了更好地了解…

手机可以搜索到wifi,但电脑搜索不到WiFi无线网络的解决方法

手机可以搜索到wifi,但电脑搜索不到WiFi无线网络的解决方法:(重点先尝试一下后面的 原因二) 手机可以搜索到wifi,但电脑搜索不到WiFi无线网络的解决方法 一般来说,手机如果可以搜索到路由器Wi-Fi无线信号,并且可以连上上网,说明路由器自身和设置肯定是没有任何问题的,这…

数据可视化-ECharts Html项目实战(7)

在之前的文章中&#xff0c;我们学习了如何设置漏斗图、仪表盘。想了解的朋友可以查看这篇文章。同时&#xff0c;希望我的文章能帮助到你&#xff0c;如果觉得我的文章写的不错&#xff0c;请留下你宝贵的点赞&#xff0c;谢谢 数据可视化-ECharts Html项目实战&#xff08;6…

学习JavaEE的日子 Day32 线程池

Day32 线程池 1.引入 一个线程完成一项任务所需时间为&#xff1a; 创建线程时间 - Time1线程中执行任务的时间 - Time2销毁线程时间 - Time3 2.为什么需要线程池(重要) 线程池技术正是关注如何缩短或调整Time1和Time3的时间&#xff0c;从而提高程序的性能。项目中可以把Time…

DataX-Oracle新增writeMode支持update

目录 前言 第一步下载源码 第二步修改源码 1、Oraclewriter 2、WriterUtil 2.1、修改getWriteTemplate方法 2.2、新增onMergeIntoDoString与getStrings方法 3、CommonRdbmsWriter 3.1、修改startWriteWithConnection 3.2、修改doBatchInsert 3.3、修改fillPreparedStatem…

Flutter 拦截系统键盘,显示自定义键盘

一、这里记录下在开发过程中&#xff0c;下单的时候输入金额需要使用自定义的数字键盘 参考链接: https://juejin.cn/post/7166046328609308685 效果图 二、屏蔽系统键盘 怎样才能够在输入框获取焦点的时候&#xff0c;不让系统键盘弹出呢&#xff1f;同时又显示我们自定义的…

【SpringBoot从入门到精通】01_SpringBoot概述

一、Spring与SpringBoot 1.1 Spring Spring 是一款目前主流的 Java EE 轻量级开源框架&#xff0c;是 Java 世界最为成功的框架之一。Spring 由“Spring 之父”Rod Johnson(罗宾约翰逊) 提出并创立&#xff0c;其目的是用于简化 Java 企业级应用的开发难度和开发周期。 广义…

新网站收录时间是多久,新建网站多久被百度收录

对于新建的网站而言&#xff0c;被搜索引擎收录是非常重要的一步&#xff0c;它标志着网站的正式上线和对外开放。然而&#xff0c;新网站被搜索引擎收录需要一定的时间&#xff0c;而且时间长短受多种因素影响。本文将探讨新网站收录需要多长时间&#xff0c;以及新建网站多久…

Prometheus +Grafana +node_exporter可视化监控Linux + windows虚机

1、介绍 待补充 2、架构图 Prometheus &#xff1a;主要是负责存储、抓取、聚合、查询方面。 node_exporter &#xff1a;主要是负责采集物理机、中间件的信息。 3、搭建过程 配置要求&#xff1a;1台主服务器 n台从服务器 &#xff08;被监控的linux或windows虚机&am…

【分布式】——CAPBASE理论

CAP&BASE理论 ⭐⭐⭐⭐⭐⭐ Github主页&#x1f449;https://github.com/A-BigTree 笔记链接&#x1f449;https://github.com/A-BigTree/tree-learning-notes ⭐⭐⭐⭐⭐⭐ Spring专栏&#x1f449;https://blog.csdn.net/weixin_53580595/category_12279588.html Sprin…