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

在开发中,我们经常使用到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.hqwc.cn/news/69616.html

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

相关文章

一生一芯4——使用星火应用商店在ubuntu下载QQ、微信、百度网盘

星火应用商店可以非常方便的完成一些应用的下载&#xff0c;下面是官方网址 http://spark-app.store/download 我使用的是intel处理器&#xff0c;无需下载依赖项&#xff0c;直接点击软件本体 我这里下载amd64,根据自己的处理器下载对应版本 sudo apt install ./spark-stor…

【es6】函数柯里化(Currying)

柯里化&#xff08;Currying&#xff09;&#xff1a;把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数&#xff0c;并且返回接受余下的参数且返回结果的新函数。 柯里化由 Christopher Strachey 以逻辑学家 Haskell Curry 命名的&#xff0c;它是 Mos…

【Linux操作系统】举例解释Linux系统编程中文件io常用的函数

在Linux系统编程中&#xff0c;文件IO操作是非常常见和重要的操作之一。通过文件IO操作&#xff0c;我们可以打开、读取、写入和关闭文件&#xff0c;对文件进行定位、复制、删除和重命名等操作。本篇博客将介绍一些常用的文件IO操作函数。 文章目录 1. open()1.1 原型、参数及…

Linux 终端命令之文件浏览(2) more

Linux 文件浏览命令 cat, more, less, head, tail&#xff0c;此五个文件浏览类的命令皆为外部命令。 hannHannYang:~$ which cat /usr/bin/cat hannHannYang:~$ which more /usr/bin/more hannHannYang:~$ which less /usr/bin/less hannHannYang:~$ which head /usr/bin/he…

自动化安装系统(一)

系统安装过程 加载boot loader加载启动安装菜单加载内核和initrd文件加载根系统运行anaconda的安装向导 安装光盘中与安装相关的文件 安装autofs启动后会自动出现/misc目录。 在虚拟机设置中添加CD/DVD&#xff0c;使用系统ISO文件&#xff0c;登录系统后mount /dev/cdrom …

css3 瀑布流布局遇见截断下一列展示后半截现象

css3 瀑布流布局遇见截断下一列展示后半截现象 注&#xff1a;css3实现瀑布流布局简直不要太香&#xff5e;&#xff5e;&#xff5e;&#xff5e;&#xff5e; 场景-在uniapp项目中 当瀑布流布局column-grap:10px 相邻两列之间的间隙为10px&#xff0c;column-count:2,2列展…

实例038 设置窗体在屏幕中的位置

实例说明 在窗体中可以设置窗体居中显示&#xff0c;本例通过设置窗体的Left属性和Top属性可以准确设置窗体的位置。运行本例&#xff0c;效果如图1.38所示。 技术要点 设置窗体在屏幕中的位置&#xff0c;可以通过设置窗体的属性来实现。窗体的Left属性表示窗体距屏幕左侧的…

【javaweb】学习日记Day1 - HTML CSS入门

目录 一、图片标签 ① 绝对路径 1.绝对磁盘路径 2.绝对网络路径 ② 相对路径 &#xff08;推荐&#xff09; 二、标题标签 三、水平线标签 四、标题样式 1、CSS引入样式 ① 行内样式 ② 内嵌样式 ③ 外嵌样式 2、CSS选择器 ① 元素选择器 ② id选择器 ③…

产品经理如何突破职业瓶颈,杀出重围?

随着社会的进步和科技的发展&#xff0c;互联网行业从未停止过发展的脚步。而在这个充满机遇和挑战的赛道上&#xff0c;互联网产品经理的角色显得尤为重要。然而&#xff0c;随着互联网产品经理的数量逐年增加&#xff0c;内卷化现象也日益严重。那么&#xff0c;产品经理应该…

GPT内功心法:搜索思维到GPT思维的转换

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…

服务器遭受攻击之后的常见思路

哈喽大家好&#xff0c;我是咸鱼 不知道大家有没有看过这么一部电影&#xff1a; 这部电影讲述了男主是一个电脑极客&#xff0c;在计算机方面有着不可思议的天赋&#xff0c;男主所在的黑客组织凭借着超高的黑客技术去入侵各种国家机构的系统&#xff0c;并引起了德国秘密警察…

Unity如何制作声音控制条(控制音量大小)

一&#xff1a;UGUI制作 1. 首先在【层级】下面创建UI里面的Slider组件。设置好它对应的宽度和高度。 2.调整Slider滑动条的填充颜色。一般声音颜色我黄色&#xff0c;所以我们也调成黄色。 我们尝试滑动Slider里面的value。 a.滑动前。 b.滑动一半。 c.滑动完。 从以上滑动va…