设计模式-迭代器模式

news2024/11/29 14:53:20

迭代器模式UML类图

实现代码如下(这里使用的集合是list,也可以使用其他集合这里就不一一展示了)

public interface Iterator<T> {
    T next();
    boolean hasNext();
}
复制代码
public class ConcreteIterator<T> implements Iterator<T>{
    private final List<T> list;
    private int cursor = 0;

    public ConcreteIterator(List<T> list){
        this.list = list;
    }

    @Override
    public T next() {
        if(hasNext()) {
            return list.get(cursor++);
        }
        return null;
    }

    @Override
    public boolean hasNext() {
        return list.size() > cursor;
    }
}
复制代码
public interface IAggregate {
    void add(User user);
    void remove(User user);

    Iterator<User> iterator();
}
复制代码
public class ConcreteAggregate implements IAggregate{
    private final List<User> users = new ArrayList<>();

    @Override
    public void add(User user) {
        users.add(user);
    }

    @Override
    public void remove(User user) {
        users.remove(user);
    }

    @Override
    public Iterator<User> iterator() {
        return new ConcreteIterator<>(users);
    }
}
复制代码
public class Test {
    public static void main(String[] args) {
        User user1 = new User("张三", "123");
        User user2 = new User("张三2", "123");
        User user3 = new User("张三3", "123");
        User user4 = new User("张三4", "123");
        User user5 = new User("张三5", "123");
        User user6 = new User("张三6", "123");
        User user7 = new User("张三7", "123");
        ConcreteAggregate concreteAggregate = new ConcreteAggregate();
        concreteAggregate.add(user1);
        concreteAggregate.add(user2);
        concreteAggregate.add(user3);
        concreteAggregate.add(user4);
        concreteAggregate.add(user5);
        concreteAggregate.add(user6);
        concreteAggregate.add(user7);
        Iterator<User> iterator = concreteAggregate.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next().toString());
        }
    }
}
复制代码

看完这些代码后可能有些人会说直接for循环不是很简单,的确很多时候for循环的确很简单,但是遇到上文中的删除操作那你的for循环是不是会有点问题,当然还有人说这个问题很好解决。当你遇到的集合是树、图再用for循环是不是很复杂,而且你的业务中有很多这样的结构的时候你的for循环是不是到处都是,如果我们写一个迭代器,复杂遍历逻辑放到迭代器里面使用到的地方只需要调用岂不是很方便,代码也相对更优雅一些

迭代器在源码中的应用

我们知道java中的集合最终都会实现Iterable接口如下图所示:

我们可以看一下Iterable源码

public interface Iterable<T> {
    Iterator<T> iterator();

    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }
    default Spliterator<T> spliterator() {
        return Spliterators.spliteratorUnknownSize(iterator(), 0);
    }
}
复制代码

发现这里就会回了迭代器再看 Iterator源码

public interface Iterator<E> {
    boolean hasNext();
    E next();
    default void remove() {
        throw new UnsupportedOperationException("remove");
    }
    default void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }
}
复制代码

发现和上文中定义的几乎一样 这里我们可以看一下迭代器的具体实现(这里拿List举例)

发现具体实现类是 ListItr再看源码:

private class ListItr extends Itr implements ListIterator<E> {
    ListItr(int index) {
        cursor = index;
    }

    public boolean hasPrevious() {
        return cursor != 0;
    }

    public E previous() {
        checkForComodification();
        try {
            int i = cursor - 1;
            E previous = get(i);
            lastRet = cursor = i;
            return previous;
        } catch (IndexOutOfBoundsException e) {
            checkForComodification();
            throw new NoSuchElementException(e);
        }
    }

    public int nextIndex() {
        return cursor;
    }

    public int previousIndex() {
        return cursor-1;
    }

    public void set(E e) {
        if (lastRet < 0)
            throw new IllegalStateException();
        checkForComodification();

        try {
            AbstractList.this.set(lastRet, e);
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }

    public void add(E e) {
        checkForComodification();

        try {
            int i = cursor;
            AbstractList.this.add(i, e);
            lastRet = -1;
            cursor = i + 1;
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }
}
复制代码

这里面就实现了List的遍历

迭代器模式的优缺点

优点:

  1. 多态迭代:为不同的聚合结构提供一致的遍历接口,即一个迭代接口可以访问不同的集合对象
  2. 简化集合对象接口:迭代器模式将集合对象本身应该提供的元索迭代接口抽取到了迭代器 中,使集合对象无须关心具体迭代行为
  3. 元素迭代功能多样化:每个集合对象都可以提供一个或多个不同的迭代器,使的同种元素聚 合结构可以有不同的迭代行为;
  4. 解耦迭代与集合:迭代器模式封装了具体的迭代算法,迭代算法的变化,不会影响到集合 对象的架构

缺点:
对于比较简单的遍历(像数组或者有序列表),使用迭代器方式遍历较为繁琐。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/87845.html

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

相关文章

商品企划VE课程大纲

课程信息 课程受众: 高中基层管理人员、储备干部&#xff0c;项目经理&#xff0c;商品企划人员&#xff0c;研发人员 课程时间: 2天 授课方式: 理论讲座&#xff0b;实战工作坊&#xff0b;录像观赏&#xff0b;角色扮演&#xff0b;提问互动&#xff0b;分组讨论&#xff0…

Java入门教程(29)——封装

封装是面向对象三大特征之一。 文章目录1.封装的特性2.封装的作用3.访问控制符4.实例1.封装的特性 高内聚、低耦合 2.封装的作用 提高代码的安全性。提高代码的复用性。高内聚&#xff1a;封装细节&#xff0c;便于修改内部代码&#xff0c;提高可维护性。低耦合”&#xff…

Linux常用目录操作及示例操作

文章目录一、常用权限操作1.1 常用权限操作1. chgrp命令2. chown命令3. chmod命令1.2 权限操作实战任务1 创建文件&#xff0c;设置其用户组任务2 修改文件的所有者任务3 修改文件操作权限二、常用目录操作2.1 常用目录操作2.2 目录操作实战任务1 获取命令帮助信息任务2 查看当…

IBM有望在2026年之前实现量子优势

&#xff08;图片来源&#xff1a;网络&#xff09; 目前&#xff0c;噪声是量子计算面临的最大挑战&#xff0c;限制了量子计算技术的快速发展。在未来几年内&#xff0c;IBM正努力通过各种类型的量子误差管理来减少噪声&#xff0c;直到实现真正的量子纠错 (QEC)。 这也是降低…

ANSYS Topology Optimization拓扑优化技术在轻量化设计应用概述

产品概念设计初期&#xff0c;单纯的凭借经验以及想象对零部件进行设计往往是不够的&#xff0c;在适当约束条件下&#xff0c;如果能充分利用“拓扑优化技术”进行分析&#xff0c;并结合丰富的产品设计经验&#xff0c;是有能力设计出更满足产品结构技术方案、工艺要求、而且…

通俗易懂的Redis数据结构基础教程

Redis有5个基本数据结构&#xff0c;string、list、hash、set和zset。它们是日常开发中使用频率非常高应用最为广泛的数据结构&#xff0c;把这5个数据结构都吃透了&#xff0c;你就掌握了Redis应用知识的一半了。 string 首先我们从string谈起。string表示的是一个可变的字节…

操作系统中的线程

我的GitHub&#xff1a;Powerveil GitHub 我的Gitee&#xff1a;Powercs12 (powercs12) - Gitee.com 皮卡丘每天学Java 进程就是 任务&#xff0c;跑起来的程序 系统使用 PCB 描述进程&#xff0c;使用双向链表来管理进程 进程存在的意义就是让操作系统可以同时执行多个任务&…

(node中)module.exports 和exports的区别

&#xff08;node中使用&#xff09;module.exports 和exports的区别是什么? 用一句话来说明就是&#xff0c;require只会去引用module.exports这个对象的导出&#xff0c;不会引用exports对象的&#xff0c;而我们在编写模块时&#xff08;初始化&#xff09;用到的exports对…

微服务框架 SpringCloud微服务架构 分布式缓存 44 Redis 分片集群 44.4 故障转移

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 分布式缓存 文章目录微服务框架分布式缓存44 Redis 分片集群44.4 故障转移44.4.1 故障转移44.4.2 数据迁移44 Redis 分片集群 44.4 故障转移…

[附源码]Python计算机毕业设计高等数学在线学习平台Django(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

零基础怎么学Python?要学多久?

首发内容&#xff0c;希望从各个角度为大家解答Python的学习方向&#xff0c;能够帮助更多入门的同学们。 一、为什么学Python 是因为铺天盖地的广告还是要转行&#xff0c;有本职工作希望自动化办公还是爱好&#xff1f; &#xff08;1&#xff09;有本职工作觉得应该学Pyt…

你一定要了解的NAT工作原理

大家好&#xff0c;我是技福的小咖老师。 前两天给大家分享了NAT策略问题的23个问题&#xff0c;有朋友私信我&#xff0c;想再普及一下NAT基础知识。今天咱们就来复习下NAT的工作原理。 随着网络应用的增多&#xff0c;IPv4地址枯竭的问题越来越严重。尽管IPv6可以从根本上解…

mybatis06:Mybatis注解开发

目录 1 MyBatis的常用注解 1.1注解完成基本的crud 例题演示 1.2mybatis的注解复杂查询映射开发 例题演示 1 MyBatis的常用注解 这几年来注解开发越来越流行&#xff0c;Mybatist也可以使用注解开发方式&#xff0c;这样我们就可以减少编写Mapper映射文件了。我们先用绕一些基…

mongoDB使用总结

windows安装 zip压缩包方式安装 下载 注意&#xff1a;因为现在最新版的mongodb不兼容win7,对windows系统的最低要求是win10。所以win7系统要安装mongodb数据库必须考虑使用旧版安装。 Download MongoDB Community Server | MongoDB 解压 将压缩包解压放在指定位置&#x…

世界杯,来一起“唠嗑”呀!

自人类诞生起&#xff0c;娱乐与社交便是融入群体、参与群体行动的“必需品”。娱乐与社交的结合使得人们更加容易找寻同类、拉近同类关系&#xff0c;而四年一届的世界杯正是娱乐与社交的完美融合体。作为全球最富影响力的体育赛事之一&#xff0c;每一届世界杯都影响着全球几…

thinkphp中 Db::query()和Db::name()区别 $db->query($sql); ->相当于访问类里面的方法

Db::query()是原生sql查询。 例如 Db::query(“select * from cmf_user where id9”); Db::name()是thinkphp基于原生sql二次封装的sql查询。 例如Db::name(‘user’)->where(‘id’,9)->find(); db是一个实例化好的数据库类&#xff0c;query是这个类里面的一个方法&am…

PMP每日一练 | 考试不迷路-12.14(包含敏捷+多选)

被延期考试的宝子 一定要坚持刷题 每日5道PMP习题助大家上岸PMP&#xff01; ​题目1-2&#xff1a; ​1.一位主要相关方要求将每日站立会议的持续时间人15分钟增加到1小时。Scrum主管应该做什么? ( ) A.接受建议并建议团队更改会议时间表 B.安排与产品负责人和团队…

内网穿透用什么软件好?本地设置内网端口映射到外网访问

我们经常听到有人说在用内网穿透工具&#xff0c;那么内网穿透工具有什么作用呢&#xff1f;内网穿透工具的作用是将本地内网服务器和应用提供到互联网上连接访问&#xff0c;可以解决在无公网IP条件下跨网互通互连问题。比如在家远程办公&#xff0c;访问公司内部办公OA服务器…

Socket.IO与Atmosphere比较

最近接到一个新需求&#xff0c;前后端保持状态连接&#xff0c;实现动态刷新的效果。那第一个想到的就是websocket&#xff0c;但是websocket我们知道有一个缺陷就是兼容性比较差&#xff08;如下图红色表示不兼容的浏览器版本&#xff09;&#xff0c;受网络限制比较大。 我…

常考vue面试题(附答案)

Vue生命周期钩子是如何实现的 vue的生命周期钩子就是回调函数而已&#xff0c;当创建组件实例的过程中会调用对应的钩子方法内部会对钩子函数进行处理&#xff0c;将钩子函数维护成数组的形式 Vue 的生命周期钩子核心实现是利用发布订阅模式先把用户传入的的生命周期钩子订阅好…