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

目录

前言

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.mzph.cn/news/776474.shtml

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

相关文章

揭秘!抖音严打AI网红骗局,维护虚拟世界秩序!

近年来&#xff0c;AI网红在社交媒体平台上的兴起引发了不少争议。为了规范虚拟人物的内容创作&#xff0c;抖音平台决定对AI网红乱象进行严厉打击&#xff0c;并推出了一系列措施。 AI-321 | 专注于AI工具分享的网站 AI工具集 | 人工智能工具箱 | 全球顶尖AI工具软件推荐与分…

Linux:环境变量的特性及获取

目录 一、环境变量基本概念 1.1命令行参数 1.2常见环境变量 二、环境变量相关指令 创建本地变量 三、环境变量通常是具有全局属性的 一、环境变量基本概念 环境变量(environment variables)不是一个而是一堆&#xff0c;彼此之间其实没有关系。本质上是为了解决不同场景下…

如何用智能AI绘一幅世界地图?

今天我们分享一下&#xff0c;用智能AI绘一幅世界地图的方法&#xff01; 为了方便你极速体验&#xff0c;特意在文末为你准备了登录帐号&#xff0c;省去你注册的烦恼。 认准AI绘画官网 如果你在百度搜索“AI绘画”或“Midjourney”&#xff0c;找出来的基本全是广告&#…

MSTP环路避免实验

思科设备参考&#xff1a; 一&#xff0c;技术简介 MSTP&#xff08;多生成树协议&#xff09;&#xff0c;MSTP解决了STP和RSTP没有考虑vlan的问题&#xff0c;STP和RSTP将所有的vlan共享为一个生成树实例&#xff0c;无法实现负载分担&#xff0c;这样就导致了网络中一些设…

【深度学习】YOLOv8:别再pip install ultralytics了

&#x1f525;博客主页&#xff1a; A_SHOWY&#x1f3a5;系列专栏&#xff1a;力扣刷题总结录 数据结构 云计算 数字图像处理 力扣每日一题_ 随着YOLOv8的版本不断更新&#xff0c;最新的几个版本会发现没有requirements.txt和setup.py&#xff0c;在安装包的依赖的时候&…

OpenAI奥特曼豪赌1.42亿破解长生不老

生物初创公司 Retro Biosciences 由山姆奥特曼投资1.42亿英镑&#xff0c;公司目标是延长人类寿命。 山姆奥特曼投资背景&#xff1a; 38 岁的奥特曼一直是科技行业的重要参与者。尽管年纪轻轻&#xff0c;奥特曼凭借 ChatGPT 和 Sora 等产品席卷了科技领域。奥特曼对 Reddit…

C语言:指针进阶

一、字符指针 char arr[] "hello";char* p "hello"; //p中存的是"hello"字符串首元素的地址printf("%c\n",*arr); //hprintf("%c\n", *p); //hprintf("%s\n", arr); //"hello",以字符串格式打印&am…

Windows安装SSH详细教程

目录 第一章:SSH简介与概念 1.1 什么是SSH? 1.2 SSH的作用 1.3 SSH的特点 1.4 SSH的应用场景 第二章:安装OpenSSH客户端 2.1 下载OpenSSH客户端 2.2 安装OpenSSH客户端 2.3 验证安装结果 第三章:配置SSH客户端 3.1 设置SSH配置文件 3.2 生成SSH密钥对 3.3 配置…

PCL点云处理之M估计样本一致性(MSAC)平面拟合(二百三十六)

PCL点云处理之M估计样本一致性(MSAC)平面拟合(二百三十五六) 一、算法介绍二、使用步骤1.代码2.效果一、算法介绍 写论文当然用RANSAC的优化变种算法MSAC啊,RANSAC太土太LOW了哈哈 MSAC算法(M-estimator Sample Consensus)是RANSAC(Random Sample Consensus)的一种…

Python入门级题目及答案

前言&#xff1a; 学习Python作为一门编程语言是非常有必要的&#xff0c;因为Python简单易学&#xff0c;功能强大&#xff0c;应用广泛。在本篇博客中&#xff0c;我们将提供八道Python入门级的题目&#xff0c;每道题目都伴有详细的描述和对应的答案代码。通过完成这八道题目…

Linux系统使用Docker部署Portainer结合内网穿透实现远程管理容器和镜像

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

Tickeys for Mac:让每一次敲击都充满乐趣,提升打字体验新高度!

Tickeys for Mac 是一款为 macOS 设计的虚拟键盘音效生成器。它通过模拟机械键盘的声音&#xff0c;为打字和输入操作增添了音效反馈&#xff0c;让用户在使用电脑时感受到更加真实的键盘反馈体验。用户可以根据个人喜好选择不同类型的键盘声音和音效设置&#xff0c;让键盘操作…

带你充分理解并掌握 vue3 的 setup 用法

在 Vue 3 中,setup 函数是 Composition API 的入口点,它提供了一种新的方式来组织和复用逻辑。setup 函数是在组件的生命周期钩子 created 之前执行的,它允许开发者在组件创建时定义响应式状态、计算属性、方法和生命周期逻辑。 基本用法 setup 函数返回一个对象,该对象的…

因子处理:/n*2-1:一个简单的标准化方法

在计算因子时候经常会使用到 rank排序&#xff0c;既将序列转换为顺序&#xff1a; s1 pd.Series([0.1,5,0.6,0.8,0.2,9]) s2 s1.rank() print(s1) print(s2)output&#xff1a; 0 0.1 1 5.0 2 0.6 3 0.8 4 0.2 5 9.0 dtype: float64 0 1.0 1 5.0 2…

【Python基础篇】那些年错过的Python

随着OpenAI的发展&#xff0c;Python的重要性不言而喻。不知你是否和我一样&#xff0c;不知道曾经说过多少次我要学Python&#xff0c;都没有执行起来… 近期我在知识库中更新了一波Python教程&#xff0c;选取了这一篇分享给大家。 前言 很多时候我们需要让程序变成交互性的…

实现DevOps需要什么?

实现DevOps需要什么&#xff1f; 硬性要求&#xff1a;工具上的准备 上文提到了工具链的打通&#xff0c;那么工具自然就需要做好准备。现将工具类型及对应的不完全列举整理如下&#xff1a; 代码管理&#xff08;SCM&#xff09;&#xff1a;GitHub、GitLab、BitBucket、SubV…

Notepad++:格式化json字符串(带转义)

目录 一、效果呈现 二、去除json字符串转义 三、格式化json字符串 一、效果呈现 格式化前 带字符串转义&#xff0c;带unicode编码字符 格式化后 二、去除json字符串转义 方法&#xff1a;采用Notepad的普通替换 第一&#xff1a;\"替换为" 第二&#xff1a;\\…

函数模板详解

大家好&#xff1a; 衷心希望各位点赞。 您的问题请留在评论区&#xff0c;我会及时回答。 一、函数模板 C另一种编程思想为&#xff1a;泛型编程&#xff0c;主要利用的技术就是模板。 C提供两种模板机制&#xff1a;函数模板、类模板 函数模板语法 函数模板作用&#xff…

有意义还是有意思?

人生苦短&#xff0c;有意思可能比有意义更重要。有意思多好玩啊&#xff0c;追逐那些有意思的事&#xff0c;才能真正顺从内心的选择。有意思的事通常都很小&#xff0c;也许找到有意思的事&#xff0c;本身就是一种幸福。 日常生活中&#xff0c;如果总在探究什么样的事情有意…

Python6:Socket编程初步学习笔记

Socket协议概要 创建socket的时候&#xff0c;需要一些选项来说明本次使用协议具体是什么&#xff0c;常用的两个&#xff1a; 由此产生的不同组合&#xff1a; 但目前TCP(IPV4)是主流&#xff0c;SOCK_STREAMAF_INET 创建和使用Socket socket模块中有socket类&#xff1a…