迭代器模式
目录:
- 需求
- 使用
- JDK源码
- 深入:为何要单独抽离出一个Iterator接口?
正文:
容器,在不同语言中都扮演着重要的角色,如Java中的List、Set和Map。迭代器模式是为容器而生的设计模式,是容器遍历的精灵。
- 第一部分:需求
1)使用者:针对多种容器,希望所有遍历方法一样,如容器更换代码无需变动
2)被使用者:不希望暴露内部实现细节,不同类型容器如何实现不需了解
- 第二部分:使用
迭代器的使用很简单,下面举例
例子1:ArrayList
public static void main(String[] args) { Collection<String> collection = new ArrayList<String>(); collection.add("开源中国"); collection.add("csdn"); collection.add("Iteye"); collection.add("黑马"); collection.add("虎嗅网"); collection.add("环球军事"); // 取得容器的迭代器 Iterator<String> iterator = collection.iterator(); // 遍历 String content = ""; while (iterator.hasNext()) { content = iterator.next(); if(content == "Iteye"){ System.out.println("Bingo Iteye"); break; } } }
迭代器的使用方式很简单,显示从容器中取得迭代器,之后根据迭代器的两个方法hasNext和next方法遍历。
例子2:更换ArrayList为HashSet
public static void main(String[] args) { Collection<String> collection = new HashSet<String>(); collection.add("开源中国"); collection.add("csdn"); collection.add("Iteye"); collection.add("黑马"); collection.add("虎嗅网"); collection.add("环球军事"); // 取得容器的迭代器 Iterator<String> iterator = collection.iterator(); // 遍历 String content = ""; while (iterator.hasNext()) { content = iterator.next(); if(content == "Iteye"){ System.out.println("Bingo Iteye"); break; } } }
例子2更换的代码很少,只需要把ArrayList更换为HashSet即可。
例子3:更换HashSet为优先队列PriorityQueue
public static void main(String[] args) { Collection<String> collection = new PriorityQueue<String>(); collection.add("开源中国"); collection.add("csdn"); collection.add("Iteye"); collection.add("黑马"); collection.add("虎嗅网"); collection.add("环球军事"); // 取得容器的迭代器 Iterator<String> iterator = collection.iterator(); // 遍历 String content = ""; while (iterator.hasNext()) { content = iterator.next(); if(content == "Iteye"){ System.out.println("Bingo Iteye"); break; } } }
依旧是简单的更换HashSet为PriorityQueue即可。
- 第三部分:JDK源码
使用上述代码,完全符合需求中的描述
1:对使用者来讲,容器遍历方法一样,改变容器类型后其他代码不需改变。
2:对被使用者容器来讲,不会暴露遍历方法实现的细节。
其实实现很简单,针对不同类型的容器,ArrayList、LinkedList、Vector或者HashSet,他们各自遍历的方法肯定不一样需要在实现类中分别做实现,然后以同一种方式进行遍历。以List为例,无论是ArrayList或者LinkedList(前者是通过数组实现,后者是通过链表实现)均继承自在AbstractList,父类AbstractList中实现了iterator方法。
public Iterator<E> iterator() { return new Itr(); }
Itr类是一个内部类
private class Itr implements Iterator<E> { int cursor = 0; int lastRet = -1; int expectedModCount = modCount; public boolean hasNext() { return cursor != size(); } public E next() { checkForComodification(); try { E next = get(cursor); lastRet = cursor++; return next; } catch (IndexOutOfBoundsException e) { checkForComodification(); throw new NoSuchElementException(); } } //其他省略 }
代码很简单,在hasNext方法中,通过记录当前遍历cursor和容器大小比较,判断是否有下一个;在next方法中,通过get方法取得下一个元素。当然,get方法是根据不同的容器有不同实现,ArrayList是通过数组下标定位,LinkedList是只能从开始通过指向下一个的引用遍历。
- 第四部分:深入
其实,总会有这样的疑问,既然不同的容器都要自己实现自己的遍历方法,那为什么不单独把hasNext方法和next方法直接放到容器里,当成是容器的成员方法?干嘛还要抽象出一个Iterator接口呢?
有人这样说:在一个复杂系统里,接口的定义其实越细越好,有助于扩展、不同部门人合作等。很有道理,只是觉得并不足以说明放在容器里而不抽象出一个接口的必须性。
个人觉得原因在于:其实对于容器来讲,它还需要支持一个基本功能即多次遍历。如下
public static void main(String[] args) { Collection<String> collection = new ArrayList<String>(); collection.add("开源中国"); collection.add("csdn"); collection.add("Iteye"); collection.add("黑马"); collection.add("虎嗅网"); collection.add("环球军事"); // 取得容器的迭代器 Iterator<String> iterator = collection.iterator(); // 遍历 String content = ""; while (iterator.hasNext()) { content = iterator.next(); if(content == "Iteye"){ System.out.println("Bingo Iteye"); break; } } //再次遍历 Iterator<String> iterator2 = collection.iterator(); while (iterator.hasNext()) { content = iterator2.next(); if(content == "csdn"){ System.out.println("Bingo csdn"); break; } } }
假设把hasNext方法和next方法当作容器的成员方法,类似在JDK中的实现,在容器里需要维护有一个变量(index)记录当前访问到第几个元素,以便和容器大小相比较,判断是否有下一个元素(hasNext方法),然后同样需要通过这个index访问元素(next方法)。
- 如果这个index是成员变量,那么该变量属于类的,不会在每次方法执行后自动消亡,第一次查找“iteye”的时候,在第3个元素中找到了它,index = 2 (下标从0 开始),我还需要查找容器是否包含字符串“csdn”,此时再次执行hasNext方法的时候,index此时是从2开始的,而我们需要的是从头开始遍历,显然不合要求
- 如果这个index放在方法体hasNext内部,每次在执行hasNext的时候确实能做到从0开始,但这样next方法又无法通过index得到该元素,因为index的作用域是hasNext方法。
- 放在一个类里就是一个很好的解决方案,每次遍历都new一个新的对象,该对象满足index从0开始,同时next方法和hasNext方法共享该变量。
在Java中每次执行Iterator方法的时候,总是new 一个新的Iterator的实现类,如HashMap中的KeyIterator。这样确保index每次都是从0开始,而且结束方法Iterator执行完毕后,hasNext方法和next方法仍能够共享变量index,因为此时这两个方法是在同一个类中。java是用内部类的方法来定义的,实际上用外围类也可以,只是内部类可以更好的隐藏细节。
相关推荐
设计模式通常分为三大类:创建型模式(关注对象的创建)、结构型模式(关注对象的组合和结构)以及行为型模式(关注对象之间的交互)。 【JDK中的设计模式】 1. **Singleton(单例模式)**:如`Runtime`和`...
设计模式分为三大类:创建型模式(如单例模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式)、结构型模式(如适配器模式、装饰器模式、代理模式、桥接模式、组合模式、外观模式、享元模式)和行为型模式(如...
这些模式被广泛应用于Java等面向对象语言中,JDK(Java Development Kit)本身就是一个很好的实践场所,因为它包含了大量使用这些设计模式的例子。下面我们将详细探讨JDK中的23个设计模式及其应用。 1. 单例模式...
迭代器在Java编程中扮演着至关重要的角色,它是一种设计模式,主要用于遍历集合类中的元素,而无需暴露集合的内部实现。迭代器模式的核心思想是解耦客户端代码与集合对象之间的关系,使得代码更加通用,易于维护。...
18. 行为型模式:如命令、解释器、迭代器、备忘录、观察者、状态、策略、模板方法、访问者模式,它们关注的是对象之间的交互和职责分配。 通过深入学习和理解这些设计模式,开发者可以写出更高质量、更具扩展性的...
迭代这个名词对于熟悉Java的人来说绝对不陌生。我们常常使用JDK提供的迭代接口进行java collection的遍历: Iterator it = list.iterator(); while(it.hasNext()){ ...而这就是关于迭代器模式应用很好的例子。
17. **迭代器模式(Iterator)**:提供一种方法顺序访问聚合对象的元素,而又不暴露其底层表示。 18. **访问者模式(Visitor)**:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变元素类的前提下...
文章目录Iterator源码剖析(一)简介(二)源码分析 ...外部迭代器的设计背后体现着迭代器设计模式的思想 (二)源码分析 该接口就只有四种方法 // 是否存在未遍历元素 boolean hasNext(); // 返回下一个元素
《设计模式——Java语言中的应用》这本书深入探讨了如何在Java中有效地运用这些模式。 1. **单例模式**:确保一个类只有一个实例,并提供全局访问点。在Java中,可以通过双重检查锁定(Double-Checked Locking)或...
_java迭代器模式详解_ ...java迭代器模式是一种非常有用的设计模式,可以使得遍历聚合对象变得更加灵活和方便。通过手动实现迭代器,我们可以隐藏聚合对象的实现细节,提供一个统一的接口来遍历聚合对象。
### Java设计模式选择题复习知识点详解 #### 工厂系列模式的优缺点 - **优点**: - **解耦**:工厂模式的...这些知识点对于深入理解和掌握设计模式至关重要,有助于提高编码质量、增强代码的可维护性和可扩展性。
Java 设计模式是软件工程中的一种重要思想,它总结了在长期的软件开发实践中,针对特定问题反复...通过阅读“Java 设计模式最佳实践”中的示例,你可以深入理解这些模式,并将它们应用到实际项目中,提升软件开发水平。
- **迭代器模式(Iterator)**:提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。 - **访问者模式(Visitor)**:表示一个作用于某对象结构中的各元素的操作。 - **备忘录模式(Memento)...
《Design Patterns设计模式速查手册HandBook系列》是由FengGe精心整理的一份关于软件设计模式的重要参考资料。这本书集合了多种经典的设计模式,主要面向Java开发者,旨在提高开发效率和代码质量,使得软件系统更加...
设计模式是软件工程中的一种最佳实践,它是在特定上下文中解决常见问题的模板。在Java中,设计模式尤其重要,因为它们有助于创建可维护、可扩展且高效的代码。本资料包含23种经典设计模式的Java实现,这些模式都是...
这本书不仅适合初学者,也适合有一定经验的开发者深入理解设计模式。Java源代码是书中理论知识的具体实现,通过实际编程加深对设计模式的理解至关重要。 1. **单例模式** (Singleton): 这是一种限制类实例化次数为...
1. 看懂源代码:如果你不懂设计模式去看Jdk、Spring、SpringMVC、IO等等等等的源码,你会很迷茫,你会寸步难行。 2. 看看前辈的代码:你去一个公司难道都是新项目让你接手?很有可能是接盘的,前辈的开发难道不用...
行为型设计模式如责任链模式、命令模式、解释器模式、迭代器模式、访问者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式和访问者模式,主要关注对象之间的交互和行为。 Spring框架,作为Java企业...
《Java设计模式》是Java开发领域的一本经典教材,由刘伟编写,深入浅出地讲解了23种GOF(GoF, Gamma, Helm, Johnson, Vlissides)设计模式,旨在提升开发者在软件设计中的灵活性和可维护性。课后习题和模拟试题是...
Java设计模式是软件开发中的重要概念,它是一种在特定情境下解决常见问题...在阅读《JAVA设计模式java 各种设计模式》的.chm文件时,你可以深入学习每个模式的原理、实现方式以及使用场景,进一步提升自己的编程技能。