本文源碼見:https://github.com/get-set/get-designpatterns/tree/master/iterator
迭代器(Iterator)模式又叫游標(Cursor)模式,通常用于集合類型來提供一種順序訪問其中元素而又不必暴漏集合的內部結構,是一種行為模式。
關于迭代器(Iterator)我想對Java Collection有過接觸的同學就不陌生,所以本文也就無需舉其他例子了,看一下在Java SDK中是如何實現的就好了。
據統(tǒng)計,java.util.ArrayList是Java SDK中使用頻率最高的類。有人說程序就是數據結構+算法,可見數據結構的重要性。我們在日常開發(fā)中,時常跟Java集合中的各種工具類打交道,對于它們,遍歷元素又是家常便飯,比如:
String[] strings = new String[]{"Hello,", "Java", "Design", "Patterns."};
List<String> stringList = Arrays.asList(strings);
Iterator<String> iterator = stringList.iterator();
while (iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
輸出即:
Hello, Java Design Patterns.
其中的Iterator就是迭代器,它有兩個核心方法:
java.util.Iterator.java(不考慮Java8新增內容)
public interface Iterator<E> {
boolean hasNext();
E next();
}
-
hasNext()用于判斷是否還有下一個元素; -
next()用于返回下一個元素,同時“看向”這個元素的再下一個元素。
我們常用的一些Java數據結構工具:

Collection是繼承自Iterable,而后者的核心方法就是返回Iterator實例的iterator()方法(不考慮Java8增加的內容的話):
java.lang.Iterable.java
public interface Iterable<T> {
Iterator<T> iterator();
}
所以我們平時使用的各種不同的List、Set和Queue的具體實現,都能返回迭代器以便能夠對它們中的元素進行遍歷。
以java.util.ArrayList為例,它的iterator()方法返回的是Iterator的其內部類的實現:
java.util.ArrayList.java
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
// 實際存儲元素的數據
transient Object[] elementData;
// 元素實際個數
private int size;
... ...
public Iterator<E> iterator() {
return new Itr();
}
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
... ...
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
... ...
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];
}
... ...
} //End of Itr
... ...
} //End of ArrayList
其中去掉了一些代碼。ArrayList是一種數組類型的List,其內部采用一個Object[]來保存所有元素,size用來保存一共有多少個元素。
方法iterator()會返回一個內部類Itr,后者實現了Iterator接口的hasNext()和next()方法。
既然是迭代遍歷,那么就需要有一個變量能夠記錄遍歷到哪個元素了,這里Itr.cursor就是用來記錄迭代索引的變量。每次調用hasNext()判斷后邊是否還有元素的時候,其實就是比較這個索引的值是否和size相等;每次調用next()返回下一個元素,其實就是返回elementData[cursor]并讓cursor自增以指向下一個元素。
這就是迭代器模式,如果去掉各種接口和類的繼承關系,簡單來說:

迭代器模式是為集合類的事物服務的,因此類關系就很好說了:一邊是集合,一邊是迭代器,集合能夠返回迭代器,迭代器能夠遍歷集合。 出于面向接口的更加靈活的模式設計,集合和迭代器均有抽象層(接口或抽象類)以及具體實現類。
最后,我們再回頭看一下本文最初的例子:
Iterator<String> iterator = stringList.iterator();
while (iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
這四行就是迭代器模式的典型用法。iterator可能是一個ArrayList返回的,可能是一個HashSet返回的,我們都不care,只要獲取到迭代器,我們就可以“無腦流”一路hasNext() + next(),這就是迭代器的初衷,它為集合封裝了迭代遍歷元素的方法,留給用戶的是一套簡單易用的遍歷接口。