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

目录

前言

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.hqwc.cn/news/576037.html

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

相关文章

Ubuntu下使用vscode进行C/C++开发:进阶篇

在vscode上进行C/C++开发的进阶需求: 1) 编写及调试源码时,可进行断点调试、可跨文件及文件夹进行函数调用。 2) 可生成库及自动提取对应的头文件和库文件。 3) 可基于当前工程资源一键点击验证所提取的库文件的正确性。 4) 可结合find_package实现方便的调用。 对于第一…

【C语言】预处理常见知识详解(宏详解)

文章目录 1、预定义符号2、define2.1 define 定义常量2.2 define 定义宏 3、#和##3.1 **#**3.2 **##** 4、条件编译&#xff08;开关&#xff09; 1、预定义符号 在C语言中内置了一些预定义符号&#xff0c;可以直接使用&#xff0c;这些符号实在预处理期间处理的&#xff0c;…

ES6 学习(三)-- es特性

文章目录 1. Symbol1.1 使用Symbol 作为对象属性名1.2 使用Symbol 作为常量 2. Iterator 迭代器2.1 for...of循环2.2 原生默认具备Interator 接口的对象2.3 给对象添加Iterator 迭代器2.4 ... 解构赋值 3. Set 结构3.1 初识 Set3.2 Set 实例属性和方法3.3 遍历3.4 相关面试题 4…

C/C++ ③ —— C++11新特性

1. 类型推导 1.1 auto auto可以让编译器在编译期就推导出变量的类型 auto的使⽤必须⻢上初始化&#xff0c;否则⽆法推导出类型auto在⼀⾏定义多个变量时&#xff0c;各个变量的推导不能产⽣⼆义性&#xff0c;否则编译失败auto不能⽤作函数参数在类中auto不能⽤作⾮静态成员…

【科技素养题】少儿编程 蓝桥杯青少组科技素养题 信息素养真题及解析第26套

少儿编程 科技素养 信息素养真题第26套 1、本次考试名称STEMA是STEM Assessment 的缩写。在保持第一个和最后一个字母不变的情况下,将 STEMA 的字母排列组合&#xff0c;一共可以组成&#xff08;&#xff09;个与原先不同的组合。 A、5 B、6 C、12 D、20 答案&#xff1a…

基础算法-去重字符串,辗转相除法,非递归前序遍历二叉树题型分析

目录 不同子串 辗转相除法-求最大公约数 二叉树非递归前序遍历 不同子串 从a开始&#xff0c;截取 a aa aaa aaab 从第二个下标开始a aa aab 从第三个 a ab 从第四个 b 使用set的唯一性&#xff0c;然后暴力遍历来去去重&#xff0c;从第一个下标开始截取aaab a aa aaa aaab…

激光是如何产生的?

激光产生的原理 美国于1960年成功研制出世界上第一台红宝石激光器&#xff0c;我国也于1961年成功研制出第一台国产红宝石激光器&#xff08;诞生于中国科学院长春光学精密机械研究所&#xff09;&#xff0c;激光技术被认为是第二个20世纪&#xff0c;继量子物理、无线电技术、…

实时数仓之实时数仓架构(Hudi)

目前比较流行的实时数仓架构有两类&#xff0c;其中一类是以FlinkDoris为核心的实时数仓架构方案&#xff1b;另一类是以湖仓一体架构为核心的实时数仓架构方案。本文针对FlinkHudi湖仓一体架构进行介绍&#xff0c;这套架构的特点是可以基于一套数据完全实现Lambda架构。实时数…

element-ui 自定义点击图标/文本/按钮触发el-date-picker时间组件,不使用插槽

天梦星服务平台 (tmxkj.top)https://tmxkj.top/#/ 1. 图片预览 2.上代码 2.1html <el-button class"hide_input" size"small"><svg t"1711608996149" class"icon" viewBox"0 0 1024 1024" version"1.1"…

Linux第85步_EXTI外部中断

1、在stm32mp157d-atk.dts文件中添加“led0”和“key0”节点 打开虚拟机上“VSCode”&#xff0c;点击“文件”&#xff0c;点击“打开文件夹”&#xff0c;点击“zgq”&#xff0c;点击“linux”&#xff0c;点击“atk-mp1”&#xff0c;点击“linux”&#xff0c;点击“my_l…

【opencv】教程代码 —ShapeDescriptors

检测和显示图像的轮廓 在图像中搜索并显示轮廓边缘多边形、轮廓矩形和包围圆 获取包含检测到的轮廓的椭圆和旋转的矩形 图像轮廓检测和轮廓凸包 计算图像中的轮廓的矩&#xff08;包括面积、重心等&#xff09;并进行显示 创建和绘制一个多边形图像然后计算并显示图像上每个点到…

[RoarCTF 2019]Online Proxy --不会编程的崽

这几天也是ctf做得有点头疼了。好些序列化的题没碰&#xff0c;一直做些sql注入类的题目。闲来无事&#xff0c;在更一次sql注入吧。 整个页面就这点信息。首先想想为什么他能获取你的ip。猜测是数据包X-Forwarded-For。 它还输出上次访问页面客户端的ip。很明显了&#xff0c…