设计模式 - 适应设计模式 - Iterator模式(一)
目录
1.什么是Iterator模式
2.为什么需要Iterator模式
3.Iterator模式的主要角色
4.总结
1.什么是Iterator模式
直接翻译的话其实是叫做迭代器模式,在英文单词中有重复做某件事情的意思。迭代器的作用就是把for循序遍历集合的这个过程抽象出来,实现在数据集合中遍历数据的功能
2.为什么需要Iterator模式
其实我们知道迭代器模式其实就是for循环,那么它跟for循环有什么区别值得我们去使用这个模式呢?我认为最重要的原因就是它可以将遍历和实现完全区分开来。我们知道我们一般使用Iterator模式实现循环遍历的话,是用以下代码实现的。
当我们使用map的时候可以这样子实现循环
Map<String,String> map=new HashMap<>();map.put("11","1");map.put("22","2");Iterator<String> mapIterator= map.keySet().iterator();while (mapIterator.hasNext()){String ss=mapIterator.next();System.out.println(ss);}
map的Iterator的具体实现类的具体方法
final class KeyIterator extends HashIteratorimplements Iterator<K> {public final K next() { return nextNode().key; }}
public final boolean hasNext() {return next != null;}
final Node<K,V> nextNode() {Node<K,V>[] t;Node<K,V> e = next;if (modCount != expectedModCount)throw new ConcurrentModificationException();if (e == null)throw new NoSuchElementException();if ((next = (current = e).next) == null && (t = table) != null) {do {} while (index < t.length && (next = t[index++]) == null);}return e;}
当我们使用list的时候可以这样子实现循环
List<String> list=new ArrayList<>();list.add("1");list.add("2");list.add("3");Iterator<String> stringIterator=list.iterator();while (stringIterator.hasNext()){String ss=stringIterator.next();System.out.println(ss);}
list的Iterator实现类的具体实现方法
public boolean hasNext() {return cursor != size;}@SuppressWarnings("unchecked")public E next() {checkForComodification();int i = cursor;if (i >= size)throw new NoSuchElementException();Object[] elementData = ArrayList.this.elementData;if (i >= elementData.length)throw new ConcurrentModificationException();cursor = i + 1;return (E) elementData[lastRet = i];}
通过上述两个小例子我们可以发现,无论我们的集合是用的什么数据结构存储数据的,我们都可以通过iterator模式来循环遍历所有数据,并且用来遍历的代码无需改变。我们实现遍历的类是Iterator的实现类,这与集合类完全剥离了开来,我们无需关心集合类的数据结构,我们只需要关心我们的迭代器即可。而迭代器的实现是集合类实现的,我们无需关心它如何实现,开箱即用就可以了。这样子不管我们是什么样的集合我们都可以用一样的方法去遍历集合
3.Iterator模式的主要角色
- Iterator(迭代器接口)
此接口定义了遍历的方法,主要是包括了hasNext和next的方法。hasNext()方法返回的是一个boolean类型的值,这个值在返回最后一个元素之前会返回true,当返回了最后一个元素之后就会返回fasle。而next()方法则会返回一个当前下标的值,之后再将下标往后移动一位。
在这里我们查看java的util包中帮我们实现的Iterator接口类,发现了不仅有hasnext和next,还添加了remove和forEachRemaining默认方法。forEachRemaining是方便我们直接遍历集合的所有数据的简便操作
public interface Iterator<E> {/*** Returns {@code true} if the iteration has more elements.* (In other words, returns {@code true} if {@link #next} would* return an element rather than throwing an exception.)** @return {@code true} if the iteration has more elements*/boolean hasNext();/*** Returns the next element in the iteration.** @return the next element in the iteration* @throws NoSuchElementException if the iteration has no more elements*/E next();/*** Removes from the underlying collection the last element returned* by this iterator (optional operation). This method can be called* only once per call to {@link #next}. The behavior of an iterator* is unspecified if the underlying collection is modified while the* iteration is in progress in any way other than by calling this* method.** @implSpec* The default implementation throws an instance of* {@link UnsupportedOperationException} and performs no other action.** @throws UnsupportedOperationException if the {@code remove}* operation is not supported by this iterator** @throws IllegalStateException if the {@code next} method has not* yet been called, or the {@code remove} method has already* been called after the last call to the {@code next}* method*/default void remove() {throw new UnsupportedOperationException("remove");}/*** Performs the given action for each remaining element until all elements* have been processed or the action throws an exception. Actions are* performed in the order of iteration, if that order is specified.* Exceptions thrown by the action are relayed to the caller.** @implSpec* <p>The default implementation behaves as if:* <pre>{@code* while (hasNext())* action.accept(next());* }</pre>** @param action The action to be performed for each element* @throws NullPointerException if the specified action is null* @since 1.8*/default void forEachRemaining(Consumer<? super E> action) {Objects.requireNonNull(action);while (hasNext())action.accept(next());}
}
mapIterator.forEachRemaining(System.out::println);
- ConcreteIterator(迭代器具体实现)
负责实现Iterator接口,在这里我们以ArrayList动态数组来查看Iterator的实现类
private class Itr implements Iterator<E> {int cursor; // index of next element to returnint lastRet = -1; // index of last element returned; -1 if no suchint expectedModCount = modCount;Itr() {}public boolean hasNext() {return cursor != size;}@SuppressWarnings("unchecked")public E next() {checkForComodification();int i = cursor;if (i >= size)throw new NoSuchElementException();Object[] elementData = ArrayList.this.elementData;if (i >= elementData.length)throw new ConcurrentModificationException();cursor = i + 1;return (E) elementData[lastRet = i];}public void remove() {if (lastRet < 0)throw new IllegalStateException();checkForComodification();try {ArrayList.this.remove(lastRet);cursor = lastRet;lastRet = -1;expectedModCount = modCount;} catch (IndexOutOfBoundsException ex) {throw new ConcurrentModificationException();}}@Override@SuppressWarnings("unchecked")public void forEachRemaining(Consumer<? super E> consumer) {Objects.requireNonNull(consumer);final int size = ArrayList.this.size;int i = cursor;if (i >= size) {return;}final Object[] elementData = ArrayList.this.elementData;if (i >= elementData.length) {throw new ConcurrentModificationException();}while (i != size && modCount == expectedModCount) {consumer.accept((E) elementData[i++]);}// update once at end of iteration to reduce heap write trafficcursor = i;lastRet = i - 1;checkForComodification();}final void checkForComodification() {if (modCount != expectedModCount)throw new ConcurrentModificationException();}}
再看看其他的Iterator实现类,例如map的keyIterator的实现类
final class KeyIterator extends HashIterator implements Iterator<K> {public final K next() { return nextNode().key; }}
abstract class HashIterator {Node<K,V> next; // next entry to returnNode<K,V> current; // current entryint expectedModCount; // for fast-failint index; // current slotHashIterator() {expectedModCount = modCount;Node<K,V>[] t = table;current = next = null;index = 0;if (t != null && size > 0) { // advance to first entrydo {} while (index < t.length && (next = t[index++]) == null);}}public final boolean hasNext() {return next != null;}final Node<K,V> nextNode() {Node<K,V>[] t;Node<K,V> e = next;if (modCount != expectedModCount)throw new ConcurrentModificationException();if (e == null)throw new NoSuchElementException();if ((next = (current = e).next) == null && (t = table) != null) {do {} while (index < t.length && (next = t[index++]) == null);}return e;}public final void remove() {Node<K,V> p = current;if (p == null)throw new IllegalStateException();if (modCount != expectedModCount)throw new ConcurrentModificationException();current = null;K key = p.key;removeNode(hash(key), key, null, false, false);expectedModCount = modCount;}}
- Aggregate(集合接口)
该角色负责定义创建Iterator角色的接口,我们来看看java的具体实现是如何的。
我们可以知道java中的Collection接口就是我们的Aggregate集合接口
public interface Collection<E> extends Iterable<E> {int size();boolean isEmpty();boolean contains(Object o);Iterator<E> iterator();...省略}
- ConcreteAggregate(集合具体实现)
从刚刚的Collection接口的注释来看,有以下接口类是实现了此接口的
* @see Set* @see List* @see Map* @see SortedSet* @see SortedMap* @see HashSet* @see TreeSet* @see ArrayList* @see LinkedList* @see Vector* @see Collections* @see Arrays* @see AbstractCollection
我们来看看实现了List接口的abstratList类,发现已经实现了Iterator的接口方法
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {public Iterator<E> iterator() {return new Itr();} ...省略
}
4.总结
使用迭代器模式,可以帮助我们将遍历和实现分离开来。如上面所示在众多迭代器的实现中,我们都可以用同一的方法去遍历,而无需关心迭代器的实现细节,这也是接口的好处,而迭代器的实现又是集合类去完成的,我们很好地将集合的遍历和集合的实现分离开来。
参考书籍 :《图解设计模式》
作者:【日】结城浩
翻译:杨文轩
设计模式 - 适应设计模式 - Iterator模式(一)相关推荐
- .Net中的设计模式——Iterator模式
在.Net中,我们很少有机会使用Iterator模式,因为.Net Framework已经运用Iterator模式为所有的集合对象实现了迭代器.我们在遍历集合对象时,喜欢使用C#提供的foreach语 ...
- 设计模式 ( 十四 ) 迭代器模式Iterator(对象行为型)
设计模式 ( 十四 ) 迭代器模式Iterator(对象行为型) 1.概述 类中的面向对象编程封装应用逻辑.类,就是实例化的对象,每个单独的对象都有一个特定的身份和状态.单独的对象是一种组织代码的有用 ...
- 设计模式——Iterator模式实现研究
导读:软件设计模式是一种表达.记录和重用软件设计结构和设计经验的新方法,它对反复出现的设计结构的关键特征进行识别.抽象和命名,使重用成功设计和结构更加容易.本文介绍了软件设计模式的特点.描述方式以及在 ...
- 设计模式学习笔记——迭代器(Iterator)模式
设计模式学习笔记--迭代器(Iterator)模式 @(设计模式)[设计模式, 迭代器模式, iterator, 迭代器] 设计模式学习笔记迭代器Iterator模式 基本介绍 迭代器案例 类图 实现 ...
- 设计模式学习总结-迭代器模式(Iterator Pattern)
问题: 在面向对象的软件设计中,经常会遇到一些聚集对象,按一定的顺序的遍历访问问题,这个遍历算法究竟应该由谁来实现呢,聚集对象本身?这样聚集对象承受了过多的功能,不仅要维护聚集对象内的元素,还要提供遍 ...
- 设计模式笔记(18)---迭代器模式(行为型)
Gof定义 提供一种方法顺序访问一个聚合对象中的各个元素, 而又不暴露该对象的内部表示. 动机 在软件构建过程中,集合对象内部结构常常变化各异.但对于这些集合对象,我们希望在不暴露其内部结构的同时,可 ...
- 【白话设计模式二】外观模式(Facade)
为什么80%的码农都做不了架构师?>>> #0 系列目录# 白话设计模式 工厂模式 单例模式 [白话设计模式一]简单工厂模式(Simple Factory) [白话设计模式二] ...
- 【白话设计模式八】命令模式(Command)
为什么80%的码农都做不了架构师?>>> #0 系列目录# 白话设计模式 工厂模式 单例模式 [白话设计模式一]简单工厂模式(Simple Factory) [白话设计模式二] ...
- 设计模式学习----装饰器模式
这两天本来是自在学习java collection Framework的Fail Fast底层机制,看到核心的部分时,突然意识到设计模式的问题,上大学到现在我还没有真正理解过设计模式的概念,于是用了大 ...
最新文章
- 实践周java基础软件开发app之五子棋
- 只用最适合的! 全面对比主流 .NET 报表控件:水晶报表、FastReport、ActiveReports 和 Stimulsoft...
- 上海教师中级职称英语计算机考试,计算机教师如果考过了软考中级对职称评定有用吗,学校会承认嘛,有人懂吗,求助...
- SAP CRM Fiori my task应用是如何在My Account应用里加载的
- vue 点击渲染ajax,vue中在页面加载时发送ajax请求获取数据渲染不到页面上
- fast路由器服务器未响应,win7系统下fast路由器进不了设置界面如何解决
- Google Adwords 关键字策略 – SEO数据搭配
- oracle报错查询动态视图,oracle基表和动态性能视图
- java cglib map转bean_Java工具集-Bean对象与Map集合相互转换工具
- 注意了!人社部宣布:未来5年,这 10 个新职业有千万缺口
- Linux vim
- CocoaPods pod install的时候报错:invalid byte sequence in UTF-8 (ArgumentError)解决办法
- 架构师重构代码的12条军规
- ecshop中$user对象
- 计算机终端保密检查 玩游戏,计算机终端保密检查系统
- 隧道监控计算机网络系统方案,高速公路隧道监控系统解决方案
- Matlab求方差,均值
- 清北学堂noip2018集训D4
- linux openerp,openerp
- 序列化-Kryo的使用详解