迭代器模式-遍历聚合对象中的元素

在开发中,我们经常使用到Iterator这个接口,我们很疑惑于这个接口的作用,认为集合已经实现了数据访问的方法,增加Iterator的意义在哪。本文我们将学习迭代器模式,用以探讨Iterator的作用。

1.1 迭代器模式概述

提供一种方法来访问聚合对象,而不用暴露这个对象的内部表示。

聚合对象拥有两个职责:1、存储数据;2、遍历数据。从依赖性来看,前者是聚合对象的基本职责,后者既是可以变化的,又是可分离的。将遍历数据的行为从聚合对象中分离出来,封装在一个被称为迭代器的对象中。由迭代器来提供遍历聚合对象内部数据的行为。

图 迭代器模式结构图

Iterator:抽象迭代器,定义了访问和遍历数据元素的接口。

ConcreteIterator:具体迭代器,实现了抽象迭代器接口,完成对聚合对象的遍历。同时通过游标来记录在聚合对象中所处的当前位置。

Aggregate:抽象聚合类,用于存储和管理元素对象。声明一个creteIterator()方法用于创建一个迭代器对象,充当抽象迭代器工厂角色。

ConcreteAggregate:具体聚合类。实现createIterator()方法,返回一个与该具体聚合类对应的具体迭代器实例。

public interface Iterator<T> {T first();T next();boolean hasNext();T currentItem();}public class ConcreteIterator<T> implements Iterator<T>{private final List<T> list;private int cursor = 0;public ConcreteIterator(ConcreteAggregate<T> list) {this.list = list.getList();}@Overridepublic T first() {return list.get(0);}@Overridepublic T next() {T t = list.get(cursor);cursor++;return t;}@Overridepublic boolean hasNext() {return cursor < list.size();}@Overridepublic T currentItem() {return list.get(cursor);}}public abstract class Aggregate<T> {protected final List<T> list = new ArrayList<>();public abstract Iterator<T> createIterator();public List<T> getList() {return list;}public void addItem(T item) {list.add(item);}}public class ConcreteAggregate<T> extends Aggregate<T>{@Overridepublic Iterator<T> createIterator() {return new ConcreteIterator<>(this);}}public class Client {public static void main(String[] args) {Aggregate<String> aggregate = new ConcreteAggregate<>();aggregate.addItem("你好");aggregate.addItem("JAVA");aggregate.addItem("Hello");aggregate.addItem("world");aggregate.addItem("是谁说的");Iterator<String> iterator = aggregate.createIterator();while (iterator.hasNext()) {System.out.println(iterator.next());}
//        运行结果:
//        你好
//        JAVA
//        Hello
//        world
//        是谁说的}}

1.1.1 使用内部类实现迭代器

具体迭代器类和具体聚合类之间存在双重关系,我们可以使用内部类(JDK中的迭代器类就是通过这种方法来实现的)来实现迭代器,这样可以对外界隐藏具体迭代器的细节。

public class InnerAggregate<T> extends Aggregate<T> {@Overridepublic Iterator<T> createIterator() {return new InnerIterator();}private class InnerIterator implements Iterator<T>{private int cursor = 0;@Overridepublic T first() {return list.get(0);}@Overridepublic T next() {T t = list.get(cursor);cursor++;return t;}@Overridepublic boolean hasNext() {return cursor < list.size();}@Overridepublic T currentItem() {return list.get(cursor);}}}public class Client {public static void main(String[] args) {Aggregate<String> aggregate = new InnerAggregate<>();aggregate.addItem("躺平");aggregate.addItem("努力");Iterator<String> iterator = aggregate.createIterator();while (iterator.hasNext())System.out.println(iterator.next());
//        运行结果:
//        躺平
//        努力}}

2 JDK Collection的迭代器

Java提供了内置迭代器,像常用的List聚合接口,其继承了Collection接口。

图 ArrayList继承类图

图 Iterable与Collection 接口声明方法

ArrayList类使用了内部类Itr来实现内部迭代器。

图 ArrayList 的内部迭代器

图 ArrayList内部迭代器的继承类图

2.1 迭代器与Foreach

Java SE5引入了Iterable接口,该接口被foreach用来在序列中移动。(Collection继承了Iterable接口)

原理:foreach语句最终被编程器转换成对iterator.next()和iterator.hasNext()方法的调用。JDK屏蔽了这些实现细节。

图 foreach Java源代码与编译后的class对比图

3 优缺点

优点:

  1. 支持以不同的方式遍历一个聚合对象,只需用一个不同的迭代器替换原有迭代器即可改变遍历算法。
  2. 简化了聚合类,聚合对象中不需要再自行提供数据遍历方法。将聚合对象的访问与内部数据的存储分离,使得访问聚合对象无须了解其内部实现细节。

缺点:

1)增加了类的个数,设计难度较大,需充分考虑到系统将来的扩展。

4 适用场景

  1. 需要为一个聚合对象提供多种遍历方式。
  2. 访问一个聚合对象的内容而无须暴露它的内部表示。

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

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

相关文章

LeetCode 160.相交链表

文章目录 &#x1f4a1;题目分析&#x1f4a1;解题思路&#x1f6a9;步骤一&#xff1a;找尾节点&#x1f6a9;步骤二&#xff1a;判断尾节点是否相等&#x1f6a9;步骤三&#xff1a;找交点&#x1f344;思路1&#x1f344;思路2 &#x1f514;接口源码 题目链接&#x1f449;…

LAXCUS分布式操作系统:技术创新引领高性能计算与人工智能新时代

随着科技的飞速发展&#xff0c;高性能计算、并行计算、分布式计算、大数据、人工智能等技术在各个领域得到了广泛应用。在这个过程中&#xff0c;LAXCUS分布式操作系统以其卓越的技术创新和强大的性能表现&#xff0c;成为了业界的佼佼者。本文将围绕LAXCUS分布式操作系统的技…

Jmeter 参数化的几种方法

目录 配置元件-用户自定义变量 前置处理器-用户参数 配置元件-CSV Data Set Config Tools-函数助手 配置元件-用户自定义变量 可在测试计划、线程组、HTTP请求下创建用户定义的变量 全局变量&#xff0c;可以跨线程组调用 jmeter执行的时候&#xff0c;只获取一次&#xff0…

LeetCode-101. 对称二叉树

Problem: 101. 对称二叉树 文章目录 思路解题方法Code结果 思路 看到这个题&#xff0c;想到的解题方法是使用递归实现。判断二叉树是否对称&#xff0c;需要判断根节点的左子树和右子树是否对称。所以从根节点开始&#xff0c;递归判断左子树的左节点是否和右子树的右节点是否…

【实战】十一、看板页面及任务组页面开发(一) —— React17+React Hook+TS4 最佳实践,仿 Jira 企业级项目(二十三)

文章目录 一、项目起航&#xff1a;项目初始化与配置二、React 与 Hook 应用&#xff1a;实现项目列表三、TS 应用&#xff1a;JS神助攻 - 强类型四、JWT、用户认证与异步请求五、CSS 其实很简单 - 用 CSS-in-JS 添加样式六、用户体验优化 - 加载中和错误状态处理七、Hook&…

NPM与外部服务的集成(上)

目录 1、关于访问令牌 1.1 关于传统令牌 1.2 关于粒度访问令牌 2、创建和查看访问令牌 2.1 创建访问令牌 在网站上创建传统令牌 在网站上创建粒度访问令牌 使用CLI创建令牌 CIDR限制令牌错误 查看访问令牌 在网站上查看令牌 在CLI上查看令牌 令牌属性 1、关于访问令…

根据二叉树创建字符串

题目:给你二叉树的根节点 root &#xff0c;请你采用前序遍历的方式&#xff0c;将二叉树转化为一个由括号和整数组成的字符串&#xff0c;返回构造出的字符串。 空节点使用一对空括号对 "()" 表示&#xff0c;转化后需要省略所有不影响字符串与原始二叉树之间的一对…

centos7安装phpipam1.4

by:铁乐与猫 date&#xff1a;2021-5-11 安装依赖 sudo yum install epel-release sudo yum install php-mcrypt安装 Apache, MySQL, PHP (LAMP) stack packages sudo yum install httpd mariadb-server php php-cli php-gd php-common php-ldap php-pdo php-pear php-snmp …

Dubbo简介

1. Dubbo是什么&#xff1f; Dubbo是一个分布式服务框架&#xff0c;致力于提供高性能和透明化的RPC远程服务调用方案&#xff0c;以及SOA服务治理方案。简单的说&#xff0c;dubbo就是个服务框架&#xff0c;如果没有分布式的需求&#xff0c;其实是不需要用的&#xff0c;只…

【计算机网络】——数据链路层

二、组帧 1、字符计数法 帧头部使用一个字符来表示帧的大小(包括第一个计数字符) &#xff08;此处一字符一个字节&#xff09; 2、字符填充收尾定界法 特定字符来定界帧的首和尾。若帧中数据段出现等同于特定字符的字符内容&#xff0c;前置一个转义字符。(类似于正则表达…

微信小程序中键盘弹起输入框自动跳到键盘上方处理

效果展示 键盘未弹起时 键盘弹起后&#xff1a; 实现方式 话就不多说了 我直接贴代码了 原理就是用你点击的输入框的底部 距离顶部的位置 减去屏幕高度除以2&#xff0c;然后设成负值&#xff0c;再将这个值给到最外层相对定位的盒子的top属性&#xff0c;这样就不会出现顶…

jvm——垃圾回收机制(GC)详解

开始之前有几个GC的基本问题 什么是GC&#xff1f; GC 是 garbage collection 的缩写&#xff0c;意思是垃圾回收——把内存&#xff08;特别是堆内存&#xff09;中不再使用的空间释放掉&#xff1b;清理不再使用的对象。 为什么要GC&#xff1f; 堆内存是各个线程共享的空间…

flutter开发实战-just_audio实现播放音频暂停音频设置音量等

flutter开发实战-just_audio实现播放音频暂停音频设置音量等 最近开发过程中遇到需要播放背景音等音频播放&#xff0c;这里使用just_audio来实现播放音频暂停音频设置音量等 一、引入just_audio 在pubspec.yaml引入just_audio just_audio: ^2.7.0在iOS上&#xff0c;video_p…

CI/CD流水线实战

不知道为什么&#xff0c;现在什么技术都想学&#xff0c;因为我觉得我遇到了技术的壁垒&#xff0c;大的项目接触不到&#xff0c;做的项目一个字辣*。所以&#xff0c;整个人心浮气躁&#xff0c;我已经得通过每天的骑行和长跑缓解这种浮躁了。一个周末&#xff0c;我再次宅在…

Docker容器基础

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、Docker概述1、docker是什么2、Docker的设计宗旨3、容器在内核中支持2种重要技术&#xff1a; 三、Docker的核心概念四、Docker相关命令1.安装依赖包2.设置阿里云…

STM32 F103C8T6学习笔记2:GPIO的认识—GPIO的基本输入输出—点亮一个LED

今日继续学习使用 STM32 F103C8T6开发板 点亮一个LED灯&#xff0c;文章提供源码&#xff0c;测试工程&#xff0c;实验效果图&#xff0c;希望我的归纳总结会对大家有帮助~ 目录 GPIO的认识与分类 &#xff1a; 引脚安排整理&#xff1a; 定时器的引脚例举&#xff1a; …

Linux:shell脚本 正则表达式与AWK

一、正则表达式 由一类特殊字符及文本字符所编写的模式&#xff0c;其中有些字符&#xff08;元字符&#xff09;不表示字符字面意义&#xff0c;而表示控制或通配的功能&#xff0c;类似于增强版的通配符功能&#xff0c;但与通配符不同&#xff0c;通配符功能是用来处理文件…

硬件产品经理:从入门到精通(新书发布)

目录 简介 新书 框架内容 相关课程 简介 在完成多款硬件产品从设计到推向市场的过程后。 笔者于2020年开始在产品领域平台输出硬件相关的内容。 在这个过程中经常会收到很多读者的留言&#xff0c;希望能推荐一些硬件相关的书籍或资料。 其实&#xff0c;笔者刚开始做硬…

【UE】Web Browser内嵌网页的使用

零、准备 1.在Edit菜单打开插件界面 搜索Web Browser并勾选&#xff0c;按提示重启引擎。 2.在资源窗口右键创建Widget Blueprint&#xff0c;并打开 3.搜索canvas panel 并拖拽到下方 4.在实验分类中找到Web Browser拖拽到Canvs Panel下 4.选中WebBrowser在右侧细节面板中…

pycharm,VSCode 几个好用的插件

pycharm Tabnine AI Code 可以在编写程序的时候为你提供一些快捷方式&#xff0c;增加编程速度 Chinese 对英文不好的程序员来说是个不错的选择&#xff0c;可以将英文状态下的pycharm变为中文版的 ChatGPT 可以跟ai聊天&#xff0c;ai可以解决你80%的问题 &#xff0c;也可以帮…