java中迭代器要导包吗_java 中迭代器的使用方法详解

java 中迭代器的使用方法详解

前言:

迭代器模式将一个集合给封装起来,主要是为用户提供了一种遍历其内部元素的方式。迭代器模式有两个优点:①提供给用户一个遍历的方式,而没有暴露其内部实现细节;②把元素之间游走的责任交给迭代器,而不是聚合对象,实现了用户与聚合对象之间的解耦。

迭代器模式主要是通过Iterator接口来管理一个聚合对象的,而用户使用的时候只需要拿到一个Iterator类型的对象即可完成对该聚合对象的遍历。这里的聚合对象一般是指ArrayList,LinkedList和底层实现为数组等拥有一组相同或相似特性的对象。通过迭代器模式对聚合对象的遍历主要是通过Iterator接口的next(),hasNext()方法进行的,这里next()方法将返回当前遍历点的元素值,而hasNext()方法则表征当前遍历点之后还有没有元素。Iterator接口中还有一个remove()方法,该方法将移除当前遍历点的元素。在一般情况下不需要使用该方法,一些特殊的情况可以调用该方法,如果当前聚合对象的遍历不支持该操作,那么可以在该方法中跑出UnSupportedOperationException。

这里我们以如下例子来对迭代器模式进行说明。现有两个餐厅的两套菜单,一套菜单是使用数组实现的,而另外一套菜单是使用ArrayList实现的。现在由于两个餐厅的合并而需要将两套菜单进行整合,由于双方的厨师都已经习惯了各自的菜单组装方式,因而都希望各自继续维护各自的菜单样式。但是,对于服务员来说,其为顾客提供菜单的时候则必须根据两套菜单进行两种不同方式的处理,这必然会增加服务员的工作难度,而且,如果后期有新的餐厅合并进来,比如其使用的菜单种类为HashMap,那么服务员将又会维护这一套菜单,这也不利于扩展。根据服务员的需求,其需要的是一个菜单列表,如果其面向的是各个不同的菜单类,那么势必会增加其工作难度,并且各个不同的菜单类中所提供的方法也不一定是服务员所需要的,因而,根据服务员的需求,这里需要制定一个菜单的规范,以实现服务员能够按照同一种方式对其进行遍历。这里就可以使用到迭代器模式,服务员只需要面向迭代器接口进行遍历,而各个厨师所拥有的菜单只需要实现该迭代器即可,其依然可以按照各自的方式维护其菜单项。这样就实现了不同的菜单与服务员的解耦。以下是使用迭代器模式解决该问题的具体代码。

菜单接口(主要包含创建迭代器的方法):

public interface Menu {

Iterator createIterator();

}

菜单项:

public class MenuItem {

private String name;

private String description;

private boolean vegetarian;

private double price;

public MenuItem(String name, String description, boolean vegetarian, double price) {

this.name = name;

this.description = description;

this.vegetarian = vegetarian;

this.price = price;

}

public String getName() {

return name;

}

public String getDescription() {

return description;

}

public boolean isVegetarian() {

return vegetarian;

}

public double getPrice() {

return price;

}

}

菜单类(菜单项的组装方式):

public class DinerMenu implements Menu {

private static final int MAX_ITEMS = 6;

private int numberOfItems = 0;

private MenuItem[] menuItems;

public DinerMenu() {

menuItems = new MenuItem[MAX_ITEMS];

addItem("Vegetarian BLT", "(Fakin') Bacon with lettuce & tomato on whole wheat", true, 2.99);

addItem("BLT", "Bacon with lettuce & tomato on whole wheat", false, 2.99);

addItem("Soup of the day", "Soup of the day, with a side of potato salad", false, 3.29);

addItem("Hotdog", "A hot dog, with saurkraut, relish, onions, topped with cheese", false, 3.05);

}

public void addItem(String name, String description, boolean vegetarian, double price) {

MenuItem menuItem = new MenuItem(name, description, vegetarian, price);

if (numberOfItems >= MAX_ITEMS) {

System.out.println("Sorry, menu is full, Can't add item to menu");

} else {

menuItems[numberOfItems] = menuItem;

numberOfItems++;

}

}

@Deprecated

public MenuItem[] getMenuItems() {

return menuItems;

}

public Iterator createIterator() {

return new DinerMenuIterator(menuItems);

}

}

public class PancakeHouseMenu implements Menu {

private ArrayList menuItems;

public PancakeHouseMenu() {

menuItems = new ArrayList<>();

addItem("K&B's Pancake Breakfast", "Pancakes with scrambled eggs, and toast", true, 2.99);

addItem("Regular Pancake Breakfast", "Pancakes with fried eggs, sausage", false, 2.99);

addItem("Blueberry Pancakes", "Pancakes made with fresh blueberries", true, 3.49);

addItem("Waffles", "Waffles, with your choice of blueberries or strawberries", true, 3.49);

}

public void addItem(String name, String description, boolean vegetarian, double price) {

MenuItem menuItem = new MenuItem(name, description, vegetarian, price);

menuItems.add(menuItem);

}

@Deprecated

public ArrayList getMenuItems() {

return menuItems;

}

public Iterator createIterator() {

return menuItems.iterator();

}

}

迭代器接口:

public interface Iterator {

boolean hasNext();

T next();

}

迭代器类:

public class DinerMenuIterator implements Iterator {

private MenuItem[] items;

private int position = 0;

public DinerMenuIterator(MenuItem[] items) {

this.items = items;

}

@Override

public boolean hasNext() {

return position < items.length && items[position] != null;

}

@Override

public MenuItem next() {

return items[position++];

}

@Override

public void remove() {

if (position <= 0) {

throw new IllegalStateException("You can't remove an item until you've done at least one next()");

}

if (items[position - 1] != null) {

for (int i = position - 1; i < items.length - 1; i++) {

items[i] = items[i + 1];

}

items[items.length - 1] = null;

}

}

}

public class PancakeHouseIterator implements Iterator {

private ArrayList items;

private int position = 0;

public PancakeHouseIterator(ArrayList items) {

this.items = items;

}

@Override

public boolean hasNext() {

return position < items.size();

}

@Override

public MenuItem next() {

return items.get(position++);

}

}

服务员类:

public class Waitress {

private Menu pancakeHouseMenu;

private Menu dinerMenu;

public Waitress(Menu pancakeHouseMenu, Menu dinerMenu) {

this.pancakeHouseMenu = pancakeHouseMenu;

this.dinerMenu = dinerMenu;

}

public void printMenu() {

Iterator pancakeIterator = pancakeHouseMenu.createIterator();

Iterator dinerIterator = dinerMenu.createIterator();

System.out.println("MENU\n----\nBREAKFAST");

printMenu(pancakeIterator);

System.out.println("\nLUNCH");

printMenu(dinerIterator);

}

private void printMenu(Iterator iterator) {

while (iterator.hasNext()) {

MenuItem menuItem = iterator.next();

System.out.print(menuItem.getName() + ", ");

System.out.print(menuItem.getPrice() + " -- ");

System.out.println(menuItem.getDescription());

}

}

}

从上面的代码可以看出,服务员并没有针对具体的菜单进行编程,而是依赖于一个创建菜单迭代器的Menu接口和一个迭代器接口Iterator来进行编程的,服务员并不需要知道所传过来的是何种组装方式的菜单,而只需要使用实现这两个接口的菜单对象进行遍历即可,这就达到了将变化的依赖于多态而实现接口,将不变的依赖于接口的目的,从而实现服务员与菜单组装方式的分离。

迭代器模式在Java类库的集合中随处可见,这里使用的Menu就相当于Java类库中的Iterable接口,其作用是创建一个迭代器对象,而Iterator接口和Java类库的Iterator接口基本一致。这里需要说明的是,实际上让一个类实现迭代器模式在为一个类增加功能的同时也增加了该类的维护负担,因为类的基本方法是高内聚的,所谓的内聚即是实现了一套相关的完整的功能,而迭代器接口实际上也是一套完整的相关的功能,因而让一个类实现迭代器模式隐含地为这个类增加了两套不那么“内聚”的两套功能,这就会导致该类在进行功能维护的时候需要兼顾双方。在Java类库中ArrayList和LinkedList中就有体现,其不仅提供了List所有的基本的remove方法,也提供了迭代器所需要实现的remove方法,为了实现两者的统一,其不得不作一些约定,比如遍历集合的时候不能调用该类基本的remove或者add等会更改该类结构的方法。

如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

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

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

相关文章

android socket 长连接_TCP/IP,http,socket,长连接,短连接

点击上方蓝色字体&#xff0c;选择“标星公众号”优质文章&#xff0c;第一时间送达上一篇&#xff1a;这300G的Java资料是我师傅当年给我的&#xff0c;免费分享给大家下一篇&#xff1a;这200G的Java实战资料是我师傅当年教我的第二招作者 | ksfzhaohui来源 | my.oschina.net…

二、Python安装扩展库

第一步:推荐easy_install工具 下载地址:https://pypi.python.org/pypi/setuptools 下载"ez_setup.py"文件; 通过运行cmd命令找到ez_setup.py文件所在目录,通过命令[python ez_setup.py]执行安装easy_install 安装成功截图 第二步:安装扩展酷 例如安装"suds"…

ORACLE 10.2.01升级10.2.05 for windows 详细文档

最近要做一个数据库的升级工作&#xff0c;提前在自己的PC机上练习了一下&#xff0c;这种文档在网上很多&#xff0c;但是大多都是使用命令编辑脚本&#xff0c;其实数据库还有一个DBUA的升级工具可以使用&#xff0c;使升级工作方便了很多。 OS环境&#xff1a;windows XP 32…

php 导出mysql 结构_导出结构和数据(如phpmyadmin)

在这里,您可以找到一个全面的解决方案来转储MySQL结构和数据,比如在PMA中(不使用exec、passthru等):它是Dszymczuk项目的一个分支,有我的增强功能。用法很简单//MySQL connection parameters$dbhost localhost;$dbuser dbuser;$dbpsw pass;$dbname dbname;//Connects to my…

tableViewCell的操作

在iOS的开发过程中&#xff0c;tableView的使用永远都是最常用的控件。今天学习了一下tableViewCell的操作。代码并不是很复杂&#xff0c;如果有OC开发经验的人&#xff0c;应该很容易看懂的。 class ViewController: UIViewController ,UITableViewDelegate, UITableViewData…

stm32正交编码器 原理图_恶劣环境下应用的电感式增量编码器和绝对编码器

编码器可分为两种基本类型 - 增量编码器和绝对编码器。增量编码器的显着特征是它报告角度的变化。换句话说&#xff0c;当增量编码器通电时&#xff0c;它不会报告其角位置&#xff0c;直到它具有测量的参考点。绝对编码器明确地在比例或范围内报告其位置。换句话说&#xff0c…

【SqlServer】Sqlserver中的DOS命令操作

输入osql ?查看是否支持当前版本&#xff0c;如果是SQL Server 2005以上用Sqlcmd , 以下用Osql连接数据库&#xff08;a&#xff09;Osql -S localhost -U username -P password(SQL Server身份验证&#xff0c;需要用户民和密码)&#xff08;b&#xff09;Osql -S localhos…

微信小程序内训笔记

2016年9月22日凌晨微信官方正式宣布“小程序”开始内测&#xff0c;有“微信之父”之称、腾讯集团高级执行副总裁张小龙在2016年末对外宣布“小程序“应用将于2017年1月9日正式推出 这一次微信还是按照惯例&#xff0c;通过机器跑出的数据&#xff0c;首先将“小程序”开放给了…

python基础代码的含义_Python基础学习篇

原标题&#xff1a;Python基础学习篇 1、编码 默认情况下&#xff0c;Python 3 源码文件以 UTF-8 编码&#xff0c;所有字符串都是unicode 字符串。 当然你也可以为源码文件指定不同的编码&#xff1a;# -*- coding: cp-1252 -*- 2、标识符 第一个字符必须是字母表中字母或下划…

java面向对象super_【JavaSE】面向对象之super、final

一、super关键字它是一个指代变量&#xff0c;用于在子类中指代父类对象。1.作用指代父类对象区分子父类同名的成员变量&#xff0c;区分父类中成员变量和子类中同名的局部变量2.使用与this相同&#xff0c;调用父类成员变量和成员方法&#xff1a;super.xx super.xxx()调用父类…

Week_1_Physical Electronics and Semiconductors

Semiconductors Fundamentals Type of solids 转载于:https://www.cnblogs.com/ronnielee/p/9579783.html

【Linux高频命令专题(23)】tar

概述 通过SSH访问服务器&#xff0c;难免会要用到压缩&#xff0c;解压缩&#xff0c;打包&#xff0c;解包等&#xff0c;这时候tar命令就是是必不可少的一个功能强大的工具。linux中最流行的tar是麻雀虽小&#xff0c;五脏俱全&#xff0c;功能强大。 tar命令可以为linux的文…

2. Add Two Numbers

直接用一个carry记录进位就可以 1 //NEW2 class Solution {3 public ListNode addTwoNumbers(ListNode l1, ListNode l2) {4 ListNode root new ListNode(0);5 return addTwoNumbers(l1, l2, root);6 }7 public ListNode addTwoNumbers(ListNode …

安装Windows更新程序遇到错误:0x80070422

看看服务那里 windows update服务是不是被禁用了&#xff1f; 还有一个问题可能是由于Windows Modules Installer被禁用了。

谈谈对python的理解_浅谈对python pandas中 inplace 参数的理解

这篇文章主要介绍了对python pandas中 inplace 参数的理解&#xff0c;具有很好的参考价值&#xff0c;希望对大家有所帮助。一起跟随小编过来看看吧 pandas 中 inplace 参数在很多函数中都会有&#xff0c;它的作用是&#xff1a;是否在原对象基础上进行修改 inplace True&am…

java中 hashset_Java中的HashSet

HashSet扩展AbstractSet并实现Set接口。它创建一个使用哈希表进行存储的集合。哈希表通过使用称为哈希的机制来存储信息。在散列中&#xff0c;键的信息内容用于确定唯一值&#xff0c;称为其散列码。然后&#xff0c;将哈希码用作存储与键关联的数据的索引。键到其哈希码的转换…

mac下的svn服务器建立

MAC下的SVN服务器建立: from : http://blog.csdn.net/q199109106q/article/details/8655204 在Windows环境中&#xff0c;我们一般使用TortoiseSVN来搭建svn环境。在Mac环境下&#xff0c;由于Mac自带了svn的服务器端和客户端功能&#xff0c;所以我们可以在不装任何第三方软件…

SQL手册

一.SQL简介 二.SQL数据类型 三.SQL语法 四.SQL SELECT语句 五.SQL INSERT语句 六.SQL UPDATE语句 七.SQL DELETE语句 八.SQL DROP语句 九.SQL CREDTE语句 十.SQL ALTER 语句总结 十一.SQL事务 十二.函数总结 十三.数据库其他操作 十四.MySQL 、SQL MS Access、和 SQL Server 数…

python语音合成并播放_使用Python实现文字转语音并生成wav文件的例子

目前手边的一些工作&#xff0c;需要实现声音播放功能&#xff0c;而且仅支持wav声音格式。 现在&#xff0c;一些网站上支持文字转语音功能&#xff0c;但是生成的都是MP3文件&#xff0c;这样还需要额外的软件来转成wav文件&#xff0c;十分麻烦。 后来&#xff0c;研究Pytho…

php 字符串 替换 最后,php如何替换字符串中的最后一个字符

php替换字符串中的最后一个字符的方法是&#xff1a;可以通过preg_replace()函数来实现。该函数的语法为&#xff1a;【preg_replace(mixed $pattern, mixed $replacement, mixed $subject】。要替换字符串中的最后一个字符&#xff0c;可以通过preg_replace()函数来实现。(如果…