智能摘要文章源自JAVA秀-https://www.javaxiu.com/34612.html
Iterator大家应该都很熟悉了,作为Java程序员的我们来说,遍历集合这也是我们刚开始学习Java知识。这次要跟大家分享的设计模式就是这迭代器模式,虽然很多语言都直接把Iterator封装到基础工具类中,但是它的特性你都了解吗?导致了数组会发生ao bing没有遍历到,因为数据迁移而丢失了。同样的假设在后面添加元素按照向后迁移,还能遍历到,那如过插入的数据是在已经遍历的之前呢?迭代器模式封装集合内部的复杂数据结构,不用关心需要遍历的对象。文章源自JAVA秀-https://www.javaxiu.com/34612.html
原文约 2378 字 | 图片 5 张 | 建议阅读 5 分钟 | 评价反馈文章源自JAVA秀-https://www.javaxiu.com/34612.html
迭代器模式
三太子敖丙 三太子敖丙 文章源自JAVA秀-https://www.javaxiu.com/34612.html
收录于话题文章源自JAVA秀-https://www.javaxiu.com/34612.html
#设计模式文章源自JAVA秀-https://www.javaxiu.com/34612.html
10个文章源自JAVA秀-https://www.javaxiu.com/34612.html
Iterator大家应该都很熟悉了,作为Java程序员的我们来说,遍历集合这也是我们刚开始学习Java知识。文章源自JAVA秀-https://www.javaxiu.com/34612.html
遍历集合的方式也有很多,比如for循环、while循环、foreach循环、Iterator等。这里的Iterator就是我们设计模式里面的迭代器模式。文章源自JAVA秀-https://www.javaxiu.com/34612.html
这次要跟大家分享的设计模式就是这迭代器模式,虽然很多语言都直接把Iterator封装到基础工具类中,但是它的特性你都了解吗?文章源自JAVA秀-https://www.javaxiu.com/34612.html
设计模式系列往期文章:文章源自JAVA秀-https://www.javaxiu.com/34612.html
单例模式文章源自JAVA秀-https://www.javaxiu.com/34612.html
工厂模式文章源自JAVA秀-https://www.javaxiu.com/34612.html
流程引擎文章源自JAVA秀-https://www.javaxiu.com/34612.html
建造者模式文章源自JAVA秀-https://www.javaxiu.com/34612.html
原型模式文章源自JAVA秀-https://www.javaxiu.com/34612.html
责任链模式文章源自JAVA秀-https://www.javaxiu.com/34612.html
观察者模式文章源自JAVA秀-https://www.javaxiu.com/34612.html
策略模式文章源自JAVA秀-https://www.javaxiu.com/34612.html
本期大纲
文章源自JAVA秀-https://www.javaxiu.com/34612.html
定义
迭代器大家都很熟悉,那么什么叫迭代器?它的目的又是什么呢?文章源自JAVA秀-https://www.javaxiu.com/34612.html
定义:我们可以用相同的方式处理集合,无论它是列表还是数组,它都提供了一种迭代其元素而不用暴露其内部结构的机制,更重要的是,不同的类型的集合都可以使用相同的统一机制,这种机制则被称为 迭代器模式。文章源自JAVA秀-https://www.javaxiu.com/34612.html
目的:提供一种顺序遍历聚合对象元素,而不暴露其内部实现的方法。文章源自JAVA秀-https://www.javaxiu.com/34612.html
以上定义来之设计模式之美文章源自JAVA秀-https://www.javaxiu.com/34612.html
解析图:文章源自JAVA秀-https://www.javaxiu.com/34612.html
文章源自JAVA秀-https://www.javaxiu.com/34612.html
Aggregate(抽象容器):负责提供创建具体迭代器角色的接口,对应于java.util.Collection接口。文章源自JAVA秀-https://www.javaxiu.com/34612.html
Iterator(抽象迭代器):迭代器的抽象类,它定义遍历容器对象的操作以及返回对象的操作文章源自JAVA秀-https://www.javaxiu.com/34612.html
ConcreteAggregate(具体容器):主要是可以实现内部不同的结构。但会暴露处理遍历容器的具体迭代器。文章源自JAVA秀-https://www.javaxiu.com/34612.html
ConcreteIterator(具体迭代器):处理特定的具体容器类的具体迭代器,实际上对于每个容器具体容器,都必须实现一个具体的迭代器。文章源自JAVA秀-https://www.javaxiu.com/34612.html
整个图看起来其实就两个东西,一个容器,一个迭代器。文章源自JAVA秀-https://www.javaxiu.com/34612.html
代码实现
这次就不举列了。直接手写一个迭代器,我们再测试一下。文章源自JAVA秀-https://www.javaxiu.com/34612.html
主要还是理解迭代器到底是干嘛用的:文章源自JAVA秀-https://www.javaxiu.com/34612.html
能在不暴露集合底层表现形式 (列表、 栈和树等) 的情况下遍历集合中所有的元素文章源自JAVA秀-https://www.javaxiu.com/34612.html
话不多说,还是直接上手撸代码文章源自JAVA秀-https://www.javaxiu.com/34612.html
public interface Aggregate { // 添加元素 void add(Object object); // 移除元素 void remove(Object object); // 迭代器 Iterator iterator();}
按照上面的类图,先是创建抽象容器,定义几个基本添加删除元素方法,以及迭代器文章源自JAVA秀-https://www.javaxiu.com/34612.html
public interface Iterator<E> { // 判断容器是否有值 boolean hasNext(); // 把游标执向下一个指针 void next(); // 当前遍历的数据 E currentItem();}
其次 再试创建抽象迭代器,遍历容器中的数据文章源自JAVA秀-https://www.javaxiu.com/34612.html
public class ConcreteAggregate implements Aggregate { private ArrayList arrayList = new ArrayList(); @Override public void add(Object object) { this.arrayList.add(object); } @Override public void remove(Object object) { this.arrayList.remove(object); } @Override public Iterator iterator() { return new ConcreteIterator(this.arrayList); }}
开始定义我们具体的容器了,内部定一个ArrayList容器,用来存放数据,当然这里大家也可以改成其他的容器 比如说用Vector 或者其他的 栈、 树、 图 等文章源自JAVA秀-https://www.javaxiu.com/34612.html
public class ConcreteIterator<E> implements Iterator<E> { private int cursor; // 游标 private ArrayList arrayList; public ConcreteIterator(ArrayList arrayList) { this.cursor = 0; this.arrayList = arrayList; } @Override public boolean hasNext() { if (this.cursor == this.arrayList.size()) { return false; } return true; } @Override public void next() { cursor++; System.out.println(cursor + " cursor"); } @Override public E currentItem() { if (cursor >= arrayList.size()) { throw new NoSuchElementException(); } E e = (E) arrayList.get(cursor); this.next(); return e; } // 测试demo public static void main(String[] args) { Aggregate aggregate = new ConcreteAggregate(); aggregate.add("java"); aggregate.add("c++"); aggregate.add("php"); aggregate.add("敖丙"); Iterator iterator = aggregate.iterator(); while (iterator.hasNext()) { System.out.println(iterator.currentItem()); } // 结果:1 java // 2 c++ // 3 php // 4 敖丙 }}
最后就是实现具体的迭代器了, 在currentItem里面根据遍历的游标,获取数组里面的值文章源自JAVA秀-https://www.javaxiu.com/34612.html
同时在main方法里面就是测试demo了,以上就是简单的手撸迭代器了。文章源自JAVA秀-https://www.javaxiu.com/34612.html
这里面我们其实还可以有其它的各种特别的玩法,比如说怎么实现暂停遍历等,只有了解内部实现,我们才能改造出符合当前所需要的业务代码。文章源自JAVA秀-https://www.javaxiu.com/34612.html
Java中的迭代器
在Java的中也有迭代器,java.util.Iterator类以及java.util.Collection,就是典型的迭代器喝容器的列子,接下来看看具体的源码文章源自JAVA秀-https://www.javaxiu.com/34612.html
文章源自JAVA秀-https://www.javaxiu.com/34612.html
文章源自JAVA秀-https://www.javaxiu.com/34612.html
当next没有值的时候则会抛出NoSuchElementException异常信息,上面的手撸异常也是根据这个来的文章源自JAVA秀-https://www.javaxiu.com/34612.html
在Java中 常见的 List、Set、Queue都是extend Collection(容器),而Collection又定义迭代器Iterator,这就是能直接使用的原因了。文章源自JAVA秀-https://www.javaxiu.com/34612.html
Java集合分析
上面我们看完了Java中的迭代器,不知道,大家注意了没有,我们在使用迭代器的时候是不能再对集合进行增减操作的,否则就会抛出ConcurrentModificationException异常文章源自JAVA秀-https://www.javaxiu.com/34612.html
那么问题来了,为什么会有这个异常信息呢?文章源自JAVA秀-https://www.javaxiu.com/34612.html
看过ArrayList源码的同学都知道底层是数据结构中的数组结构的,所以我们看下接下来图结构文章源自JAVA秀-https://www.javaxiu.com/34612.html
文章源自JAVA秀-https://www.javaxiu.com/34612.html
假设现在开始在遍历当前这个数组,当从第一步执行到第二步,都是正常运行的,假设现在执行完第二步,开始走第三步时文章源自JAVA秀-https://www.javaxiu.com/34612.html
删除 java这个元素,数组为了保持存储数据的连续性,当删除java数据时,是会发生数组元素的迁移的。所以正常步骤3应该是遍历到aobing元素的变成当前数组元素已经是ao bing了。文章源自JAVA秀-https://www.javaxiu.com/34612.html
导致了数组会发生ao bing没有遍历到,因为数据迁移而丢失了。文章源自JAVA秀-https://www.javaxiu.com/34612.html
同样的假设在后面添加元素按照向后迁移,还能遍历到,那如过插入的数据是在已经遍历的之前呢?文章源自JAVA秀-https://www.javaxiu.com/34612.html
这样整个遍历就变成不可预估了。文章源自JAVA秀-https://www.javaxiu.com/34612.html
public static void main(String[] args) { List<String> aggregate = new ArrayList(); aggregate.add("java"); aggregate.add("c++"); aggregate.add("php"); aggregate.add("敖丙"); Iterator<String> iterator = aggregate.iterator(); while (iterator.hasNext()) { iterator.remove(); // 添加这行代码 java.lang.IllegalStateException System.out.println(iterator.next()); iterator.remove(); // 正常 } }
再来看这个测试demo,同样都是调用remove方法,不同的地方结果不一样,这也就是刚好印证上面的图体现的问题,所以要解决这个问题,要么就是遍历的时候不允许增删元素,要么是增删元素之后让遍历报错。文章源自JAVA秀-https://www.javaxiu.com/34612.html
通过上面的列子已经了解了迭代器的原理以及实现,大家可以根据自己所需要的场景改造迭代器,很多公司的一些自己的框架或者工具类等等都是通过现有框架源码进行改造而来。文章源自JAVA秀-https://www.javaxiu.com/34612.html
迭代器的优点:文章源自JAVA秀-https://www.javaxiu.com/34612.html
迭代器模式封装集合内部的复杂数据结构,不用关心需要遍历的对象。文章源自JAVA秀-https://www.javaxiu.com/34612.html
符合单一职责原则以及开闭原则文章源自JAVA秀-https://www.javaxiu.com/34612.html
可以对遍历进行把控暂停或者继续文章源自JAVA秀-https://www.javaxiu.com/34612.html
总结
迭代器设计模式在我们业务场景中自己写的代码中 我个人是觉得比较少见的,至少到目前我还没有怎么发现有好的业务场景可以用这个模式,所以这里我就不给大家举例业务代码改造了。(毕竟不能因为设计模式而强行设计)文章源自JAVA秀-https://www.javaxiu.com/34612.html
跟大家分享迭代器主要是想让大家了解Java集合遍历怎么实现的,方便我们提升自己以后的看源码的能力,以及提升自己的设计能力。文章源自JAVA秀-https://www.javaxiu.com/34612.html
后面就再跟大家再聊聊动态代理设计模式,就不会再详细讲了其他的模式了,因为本身不怎么常见,作为了解还是会和大家做一个总结分享。文章源自JAVA秀-https://www.javaxiu.com/34612.html
今天的迭代器模式到此结束,我是敖丙,你知道的越多,你不知道的越多,我们下期见!!!文章源自JAVA秀-https://www.javaxiu.com/34612.html

评论