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

前言:
迭代器模式将一个集合给封装起来,主要是为用户提供了一种遍历其内部元素的方式。迭代器模式有两个优点:①提供给用户一个遍历的方式,而没有暴露其内部实现细节;②把元素之间游走的责任交给迭代器,而不是聚合对象,实现了用户与聚合对象之间的解耦。
迭代器模式主要是通过Iterator接口来管理一个聚合对象的,而用户使用的时候只需要拿到一个Iterator类型的对象即可完成对该聚合对象的遍历。这里的聚合对象一般是指ArrayList,LinkedList和底层实现为数组等拥有一组相同或相似特性的对象。通过迭代器模式对聚合对象的遍历主要是通过Iterator接口的next(),hasNext()方法进行的,这里next()方法将返回当前遍历点的元素值,而hasNext()方法则表征当前遍历点之后还有没有元素。Iterator接口中还有一个remove()方法,该方法将移除当前遍历点的元素。在一般情况下不需要使用该方法,一些特殊的情况可以调用该方法,如果当前聚合对象的遍历不支持该操作,那么可以在该方法中跑出UnSupportedOperationException。
这里我们以如下例子来对迭代器模式进行说明。现有两个餐厅的两套菜单,一套菜单是使用数组实现的,而另外一套菜单是使用ArrayList实现的。现在由于两个餐厅的合并而需要将两套菜单进行整合,由于双方的厨师都已经习惯了各自的菜单组装方式,因而都希望各自继续维护各自的菜单样式。但是,对于服务员来说,其为顾客提供菜单的时候则必须根据两套菜单进行两种不同方式的处理,这必然会增加服务员的工作难度,而且,如果后期有新的餐厅合并进来,比如其使用的菜单种类为HashMap,那么服务员将又会维护这一套菜单,这也不利于扩展。根据服务员的需求,其需要的是一个菜单列表,如果其面向的是各个不同的菜单类,那么势必会增加其工作难度,并且各个不同的菜单类中所提供的方法也不一定是服务员所需要的,因而,根据服务员的需求,这里需要制定一个菜单的规范,以实现服务员能够按照同一种方式对其进行遍历。这里就可以使用到迭代器模式,服务员只需要面向迭代器接口进行遍历,而各个厨师所拥有的菜单只需要实现该迭代器即可,其依然可以按照各自的方式维护其菜单项。这样就实现了不同的菜单与服务员的解耦。以下是使用迭代器模式解决该问题的具体代码。
菜单接口(主要包含创建迭代器的方法):
public interface Menu<T> {
Iterator<T> 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<MenuItem> {
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<MenuItem> createIterator() {
return new DinerMenuIterator(menuItems);
}
}
public class PancakeHouseMenu implements Menu<MenuItem> {
private ArrayList<MenuItem> 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<MenuItem> getMenuItems() {
return menuItems;
}
public Iterator<MenuItem> createIterator() {
return menuItems.iterator();
}
}
迭代器接口:
public interface Iterator<T> {
boolean hasNext();
T next();
}
迭代器类:
public class DinerMenuIterator implements Iterator<MenuItem> {
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<MenuItem> {
private ArrayList<MenuItem> items;
private int position = 0;
public PancakeHouseIterator(ArrayList<MenuItem> 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<MenuItem> pancakeHouseMenu;
private Menu<MenuItem> dinerMenu;
public Waitress(Menu<MenuItem> pancakeHouseMenu, Menu<MenuItem> dinerMenu) {
this.pancakeHouseMenu = pancakeHouseMenu;
this.dinerMenu = dinerMenu;
}
public void printMenu() {
Iterator<MenuItem> pancakeIterator = pancakeHouseMenu.createIterator();
Iterator<MenuItem> dinerIterator = dinerMenu.createIterator();
System.out.println("MENU\n----\nBREAKFAST");
printMenu(pancakeIterator);
System.out.println("\nLUNCH");
printMenu(dinerIterator);
}
private void printMenu(Iterator<MenuItem> 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等会更改该类结构的方法。
如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
# java
# 迭代器
# 迭代器的使用方法
# 迭代器详解
# Java基于迭代器模式实现的访问人员列表操作示例
# 23种设计模式(14)java迭代器模式
# Java编程Iterator迭代器设计原理及实现代码示例
# java 迭代器模式实例详解
# 详解Java中Iterator迭代器的用法
# 详解Java中的迭代迭代器Iterator与枚举器Enumeration
# java集合迭代器Iterator中的remove陷阱
# Java中Set&List的迭代器实现步骤解析
# 迭代
# 遍历
# 的是
# 两套
# 只需要
# 类库
# 主要是
# 菜单项
# 实现了
# 所需要
# 依赖于
# 增加了
# 这一
# 就有
# 不需要
# 如有
# 是指
# 两种
# 这也
# 这就
相关文章:
如何制作算命网站,怎么注册算命网站?
魔毅自助建站系统:模板定制与SEO优化一键生成指南
网站插件制作软件免费下载,网页视频怎么下到本地插件?
如何快速搭建高效香港服务器网站?
网站制作多少钱一个,建一个论坛网站大约需要多少钱?
网站建设制作需要多少钱费用,自己做一个网站要多少钱,模板一般多少钱?
手机钓鱼网站怎么制作视频,怎样拦截钓鱼网站。怎么办?
保定网站制作方案定制,保定招聘的渠道有哪些?找工作的人一般都去哪里看招聘信息?
沈阳个人网站制作公司,哪个网站能考到沈阳事业编招聘的信息?
建站主机默认首页配置指南:核心功能与访问路径优化
成都网站制作公司哪家好,四川省职工服务网是做什么用?
宝塔Windows建站如何避免显示默认IIS页面?
如何选择靠谱的建站公司加盟品牌?
建站之星上传入口如何快速找到?
如何在宝塔面板中创建新站点?
如何选择高效响应式自助建站源码系统?
常州自助建站费用包含哪些项目?
如何解决VPS建站LNMP环境配置常见问题?
个人网站制作流程图片大全,个人网站如何注销?
太原网站制作公司有哪些,网约车营运证查询官网?
常州企业网站制作公司,全国继续教育网怎么登录?
网站制作怎么样才能赚钱,用自己的电脑做服务器架设网站有什么利弊,能赚钱吗?
如何快速搭建二级域名独立网站?
如何通过云梦建站系统实现SEO快速优化?
公司网站设计制作厂家,怎么创建自己的一个网站?
东莞专业制作网站的公司,东莞大学生网的网址是什么?
关于BootStrap modal 在IOS9中不能弹出的解决方法(IOS 9 bootstrap modal ios 9 noticework)
如何快速搭建高效服务器建站系统?
jQuery 常见小例汇总
如何在万网自助建站平台快速创建网站?
网站按钮制作软件,如何实现网页中按钮的自动点击?
招贴海报怎么做,什么是海报招贴?
香港服务器网站卡顿?如何解决网络延迟与负载问题?
佛山企业网站制作公司有哪些,沟通100网上服务官网?
如何在Windows服务器上快速搭建网站?
武汉网站如何制作,黄黄高铁武穴北站途经哪些村庄?
大同网页,大同瑞慈医院官网?
如何用5美元大硬盘VPS安全高效搭建个人网站?
如何做静态网页,sublimetext3.0制作静态网页?
单页制作网站有哪些,朋友给我发了一个单页网站,我应该怎么修改才能把他变成自己的呢,请求高手指点迷津?
如何确保西部建站助手FTP传输的安全性?
网站制作哪家好,cc、.co、.cm哪个域名更适合做网站?
如何在阿里云部署织梦网站?
完全自定义免费建站平台:主题模板在线生成一站式服务
电商平台网站制作流程,电商网站如何制作?
网站制作公司,橙子建站是合法的吗?
济南企业网站制作公司,济南社保单位网上缴费步骤?
香港服务器如何优化才能显著提升网站加载速度?
PHP正则匹配日期和时间(时间戳转换)的实例代码
*请认真填写需求信息,我们会在24小时内与您取得联系。