遍历元素在编程中十分常用,毋庸置疑只要是一个容器,都应该提供遍历其内部元素的方式,这就是本文介绍的迭代器模式。
1.迭代器模式
迭代器模式(Iterator pattern) 提供一个迭代器,它可以按顺序遍历并访问容器中的元素,而无需暴露迭代器的内部实现。
迭代器模式如此常用,以至于Java标准库中,已经在各个容器类中集成了获取迭代器的方法,iterator(),我们使用List的时候根本无需自己去实现迭代器。
但是还是时候需要根据自己的算法来访问元素,比如按照某种递增的规律,某种顺序等等,这样,你就需要自己实现迭代器了。
迭代器模式UML类图如下所示:
一般实现步骤如下:
- 定义一个容器类,添加一个可以获取Iterator的方法,比如iterator();
- 设计Iterator类, 封装遍历容器元素的算法;
- 客户端调用容器的iterator()方法获取该容器的迭代器iterator;
- 客户端使用itreator的first(), next(), hasNext()等方法访问元素。
Java中,已经给我们提供了一个迭代器的接口Iterator<E>, 通过实现它可以定义自己的迭代器;同时,Java提供了一个Iterable<T>接口,容器实现Iterable接口的iterator()方法可获取相应的迭代器。
2. 代码实现
下面我定义一个容器实现Iterable接口,通过iterator方法获取迭代器,实现对fibonacci数列的遍历。
Iterable接口就相当于UML类图中的TraversalAbstraction, Fibonacci相当于Collection, 实现Iterable,并提供获取iterator的方法。
/** * Fibonacci 数列的"容器",通过构造器传入整数值设置该对象保存多少个数。 * JDK提供了现成的Iterable接口,实现该接口即可获取Fibonacci对象的迭代器。 */ class Fibonacci implements Iterable<Integer> { /** 需要取多少数字 */ private final int count; public Fibonacci(int count) { this.count = count; } private int fib(int n) { if (n <= 2) { return 1; } return fib(n - 2) + fib(n - 1); } /** 根据该方法获取迭代器 */ @Override public Iterator<Integer> iterator() { // 使用匿名内部类实现自己的遍历算法 return new Iterator<Integer>() { int n = 1; int total = count; @Override public boolean hasNext() { return total > 0; } @Override public Integer next() { if (total-- > 0) { return fib(n++); } throw new RuntimeException("no more!"); } }; } }
构造元素数量为6的斐波那契数列,并获取其迭代器iterator遍历各个元素
public class IteratorDemo { public static void main(String[] args) { Fibonacci fibonacci = new Fibonacci(6); Iterator<Integer> iterator = fibonacci.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } } }
输出结果
1 1 2 3 5 8
大学之道,在明明德,在亲民,在止於至善