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

news2024/11/23 12:23:21

目录

前言

UML

plantuml

类图

实战代码

Iterator

ArrayList

Client

自定义迭代器

TreeNode

TreeUtils

Client


前言

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

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

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

UML

plantuml

@startuml
'https://plantuml.com/class-diagram

interface Iterator {
    + hasNext() : boolean
    + next() : type
}

class ConcreteIterator {
    + hasNext() : boolean
    + next() : type
}

class Client {
    + iterator() : Iterator
}

Iterator <|.. ConcreteIterator

Client ..> 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);
        }

        @Override
        public boolean hasNext() {
            return !stack.isEmpty();
        }

        @Override
        public 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.coloradmin.cn/o/1546839.html

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

相关文章

MyBatis是纸老虎吗?(七)

在上篇文章中&#xff0c;我们对照手动编写jdbc的开发流程&#xff0c;对MyBatis进行了梳理。通过这次梳理我们发现了一些之前文章中从未见过的新知识&#xff0c;譬如BoundSql等。本节我想继续MyBatis这个主题&#xff0c;并探索一下MyBatis中的缓存机制。在正式开始梳理前&am…

Python自动化测试环境搭建

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号&#xff1a;互联网杂货铺&#xff0c;回复1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 请事先自行安装好​​Pycharm​​​软件哦&#xff0c;我…

【Python系列】获取字符串的长度

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

Clip Converter - 视频在线下载方法

Clip Converter - 视频在线下载方法 1. Video URL to Download2. Continue3. StartReferences YT to MP4 & MP3 Converter! https://www.clipconverter.cc/ Clip Converter is a free online media conversion application, which allows you to reocord, convert and do…

基于冠豪猪优化器(CPO)的无人机路径规划

该优化算法是2024年新发表的一篇SCI一区top论文具有良好的实际应用和改进意义。一键运行main函数代码自动保存高质量图片 1、冠豪猪优化器 摘要&#xff1a;受冠豪猪(crest Porcupine, CP)的各种防御行为启发&#xff0c;提出了一种新的基于自然启发的元启发式算法——冠豪猪…

#Linux系统编程(ps和kill命令)

&#xff08;一&#xff09;发行版&#xff1a;Ubuntu16.04.7 &#xff08;二&#xff09;记录&#xff1a; &#xff08;1&#xff09;ps命令 可以列出系统中当前运行的那些进程。 命令格式&#xff1a;ps 参数(常用-aux) 命令功能&#xff1a;用来显示当前进程的状态 常…

应急响应实战笔记04Windows实战篇(2)

第2篇&#xff1a;蠕虫病毒 0x00 前言 ​ 蠕虫病毒是一种十分古老的计算机病毒&#xff0c;它是一种自包含的程序&#xff08;或是一套程序&#xff09;&#xff0c;通常通过网络途径传播&#xff0c;每入侵到一台新的计算机&#xff0c;它就在这台计算机上复制自己&#xff…

Star 5.3k!纯Python开发的高效SQL 解析器!

目前从事大数据相关的开发&#xff0c;都离不开SQL&#xff0c;不管是关系型数据库还是非关系型数据&#xff0c;在做不同数据库间迁移或者转换的时候都会用到SQL转换。今天来为大家分享一个有趣的开源项目&#xff0c;SQLGlot&#xff0c;一个纯Python开发的SQL转换器&#xf…

VMware扩容硬盘

最近研究Oracle的备份导入导出功能&#xff0c;但是因为磁盘容量不够导致表空间的扩容没办法&#xff0c;从而没办法导入数据库的dmp文件。得想办法先扩容磁盘容量。话不多说上截图操作。 操作环境&#xff1a;VMware10 , Centos 6.9 VMware扩容硬盘步骤 一、关闭虚拟机&…

sizeof和strlen的使用及差异

sizeof 1.sizeof是操作符 2.sizeof计算操作数所占内存的大小&#xff0c;单位是字节&#xff08;byte&#xff09; 3.sizeof不关注内存中存放什么数据 4.sizeof比较通用不挑类型 strlen 1.strlen是库函数&#xff0c;使用需包含头文件string.h 2.strlen是求字符串长度的&#x…

L1-2 倒数第N个字符串

本题链接&#xff1a;PTA | 程序设计类实验辅助教学平台 题目&#xff1a; 样例&#xff1a; 输入 3 7417 输出 pat 思路&#xff1a; 根据题意&#xff0c;这道题是一道思维模拟题。 给出 n 位的小写字母字符串&#xff0c;其中进制位为 26 &#xff0c;求进位1 到 倒数第 …

天工AI搜索引擎

相信正在看autosar架构相关内容的人来说&#xff0c;对于autosar相关知识或者配置项的生涩知识点可谓是苦之久矣&#xff0c;这个时候一个好的搜索引擎能带来的帮助太大了&#xff0c;不管是平时百度还是看文档都需要大量的时间去检索自己真正想知道的信息&#xff0c;偶然间发…

酒店管理系统【GUI/Swing+MySQL】(Java课设)

系统类型 Swing窗口类型Mysql数据库存储数据 使用范围 适合作为Java课设&#xff01;&#xff01;&#xff01; 部署环境 jdk1.8Mysql8.0Idea或eclipsejdbc 运行效果 本系统源码地址&#xff1a;https://download.csdn.net/download/qq_50954361/89036287 更多系统资源库…

Windows 频繁失去焦点分析

原文&#xff1a;https://blog.iyatt.com/?p14383 1 前言 刚才在打字的时候发现会随机失去焦点&#xff0c;然后又要用鼠标点一下正在输入的位置才能继续输入&#xff0c;特别烦。开始我怀疑是手碰到触摸板导致失去焦点&#xff0c;但是我用了差不多十年带触摸板的笔记本电脑…

Python框架篇(7):FastApi-依赖项

有时选择太多也会让人陷入焦虑&#xff0c;比如突然有一段自由时间&#xff0c;却因为想做的事情太多&#xff0c;最后把时间都浪费在了摇摆不定上&#xff0c;静不下心做最重要的事&#xff0c;或者说根本不知道最重要的事情是什么。---------- 《认知觉醒:开启自我改变的原动…

【干货】无源滤波器设计讲解,工作原理+设计步骤

今天给大家分享的是&#xff1a;无源模拟滤波器针对很多入门小白不懂滤波器设计&#xff0c;一些老工程师上班很多年有的也不懂得总结知识点&#xff0c;以及想学习不知道怎么系统学习的这一类人群&#xff0c;前方知识点来袭&#xff0c;请君放心食用~ 在信号处理领域&#x…

AXI-Stream——草稿版

参考自哔站&#xff1a;FPGA IP之AXI4-Lite AXI4-Stream_哔哩哔哩_bilibili 信号 传输层级从小到大 TKEEP和TSTRB共同决定了是哪种数据流

红外循迹,避障模块介绍

本节将介绍标题中三种模块的应用以及工作原理 上图中&#xff0c;黑色的是红外接收管&#xff0c;绿色的是红外发射管&#xff0c;他俩与发光二级管都非常像&#xff0c;但功能上却有所不同。 发光二级管&#xff1a;亮度在一定的时间内随电流的增大而增大。 红外发射管&…

Python遥感开发之解决TIF数据之间行列不一致的问题

Python遥感开发之解决TIF数据之间行列不一致的问题 1.问题如图所示2.完整代码如下所示 前言&#xff1a;主要解决在同一分辨率的情况下&#xff0c;遥感数据之间行和列数据不一致的问题。 1.问题如图所示 我们发现这两个TIF的分辨率是一样的&#xff0c;都是0.01x0.01&#xff…

软考软件设计师2024年5月报名流程及注意事项

2024年5月软考软件设计师报名入口&#xff1a; 中国计算机技术职业资格网&#xff08;http://www.ruankao.org.cn/&#xff09; 2024年软考报名时间暂未公布&#xff0c;考试时间上半年为5月25日到28日&#xff0c;下半年考试时间为11月9日到12日。不想错过考试最新消息的考友…