Day42【概念解析】迭代器模式
目录 ▼
整理定义
中文名称:迭代器模式
英文名称:iterator pattern
复述展开
What is iterator pattern?
📌 迭代器模式是一种行为设计模式。它通过迭代器来访问容器的全体对象,在不暴露对象的内部结构的同时,提供一种顺序遍历全体对象。它能够将算法与容器解耦。
🌰*1
图书馆的书籍管理:在图书馆中,我们可以使用迭代器模式来遍历书架上的所有书籍。每一本书都可以被看作是一个元素,而书架则是一个聚合对象。我们可以创建一个迭代器,用于遍历书架上的每一本书,而无需知道书架的内部结构。
🌰*2
电视遥控器:电视遥控器上的频道切换按钮就是一个迭代器模式的例子。当我们按下频道切换按钮时,电视会按照一定的顺序切换到下一个频道。在这个过程中,我们无需知道电视内部如何存储和管理这些频道,只需要使用遥控器上的按钮就可以遍历所有的频道。
🌰*3
在Java的容器中,像 ArrayList 就提供了 iterator 方法,提供了可以遍历使用的迭代器。
import java.util.ArrayList;
import java.util.Iterator;
public class Main {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("Apple");
list.add("Banana");
list.add("Cherry");
Iterator<String> it = list.iterator();
while(it.hasNext()){
String fruit = it.next();
System.out.println(fruit);
}
}
}
使用ArrayList的迭代器时,有一些注意事项:
-
并发修改:如果在使用迭代器遍历ArrayList的过程中,对ArrayList进行了结构性修改(如添加、删除元素),那么将会抛出ConcurrentModificationException。为了避免这种情况,可以使用迭代器的remove()方法来删除元素,或者使用CopyOnWriteArrayList。
-
next()方法的使用:在调用next()方法获取下一个元素之前,应该先调用hasNext()方法检查是否还有下一个元素。如果没有下一个元素,但是仍然调用了next()方法,那么将会抛出NoSuchElementException。
-
迭代器的单向性:ArrayList的迭代器是单向的,也就是说,它只能从前向后遍历元素,不能从后向前遍历。如果需要从后向前遍历元素,可以使用ListIterator。
迭代器模式的结构

-
迭代器 (Iterator) 接口声明了遍历集合所需的操作: 获取下一个元素、 获取当前位置和重新开始迭代等。
-
具体迭代器 (Concrete Iterators) 实现遍历集合的一种特定算法。 迭代器对象必须跟踪自身遍历的进度。 这使得多个迭代器可以相互独立地遍历同一集合。
-
集合 (Collection) 接口声明一个或多个方法来获取与集合兼容的迭代器。 请注意, 返回方法的类型必须被声明为迭代器接口, 因此具体集合可以返回各种不同种类的迭代器。
-
具体集合 (Concrete Collections) 会在客户端请求迭代器时返回一个特定的具体迭代器类实体。 你可能会琢磨, 剩下的集合代码在什么地方呢? 不用担心, 它也会在同一个类中。 只是这些细节对于实际模式来说并不重要, 所以我们将其省略了而已。
-
客户端 (Client) 通过集合和迭代器的接口与两者进行交互。 这样一来客户端无需与具体类进行耦合, 允许同一客户端代码使用各种不同的集合和迭代器。
优缺点
优点:
-
单一职责原则。 通过将体积庞大的遍历算法代码抽取为独立的类, 你可对客户端代码和集合进行整理。
-
开闭原则。 你可实现新型的集合和迭代器并将其传递给现有代码, 无需修改现有代码。
-
你可以并行遍历同一集合, 因为每个迭代器对象都包含其自身的遍历状态。
-
相似的, 你可以暂停遍历并在需要时继续。
缺点:
-
如果你的程序只与简单的集合进行交互, 应用该模式可能会矫枉过正。
-
对于某些特殊集合, 使用迭代器可能比直接遍历的效率低。
理解体会
迭代器模式在实际的代码开发中随处可见,Java所有的容器都需要实现 Iterator 这个接口,并提供next() 方法进行顺序遍历。
在Python中,for i in range(10) 就是一个非常简单的迭代器,这个for 循环可以从0遍历到9。
掌握好迭代器也是非常重要的。