迭代器是一种常用的模式,习惯上称之为“迭代器模式”或“Iterator模式”。该模式是用于遍历集合类的标准访问方法。它可以把访问逻辑从不同类型的集合类中抽象出来,从而避免向客户端暴露集合的内部结构。
如果没有使用迭代器模式,我们如果想要遍历一个ArrayList代码只能用下面的实现
for (int i = 0; i < list.size(); i ++){ list.get(i); }
这种方法程序员必须事先知道几何的内部结构,访问代码和集合本身是紧耦合,无法将访问逻辑从集合类和客户端代码中分离出来,每一种集合对应一种遍历方法,客户端代码无法复用。而且如果想要遍历Set类型的集合,java类库中并没有提供合适的方法,更糟的是假设程序员在程序运行一段时间后发现需要一个不能有重复成员的集合,此时将List更改成Set完全无法工作,因为Set接口没有get方法。
而Iterator模式则规定对所有的集合采用同一种方式遍历成员,在Java类库中,所有实现Collection接口的类都可以通过方法iterator()获取一个能够遍历其所有成员的迭代器,因此,上面的例子改成下面的代码后,如果想要更改List接口为Set接口将是轻而易举的事情;
Iteator iter = list.iterator(); while (iter.hasNext()){ iter.next(); }
转变成Set接口只要修改一处代码即可
Iteator iter = set.iterator(); while (iter.hasNext()){ iter.next(); }
所有类型集合生成的迭代器都必须实现Iterator接口,但是其实现方式可以完全不一样,只要实现了Iterator接口以下三个方法就可以了;
boolean hashNext(); Object next(); void remove();
下面来看一下AbstractList类的迭代器是如何实现的,其iterator()方法的代码如下:
public Iterator iterator(){ return new Itr(); }
这里创建并返回了一个Itr类型的对象,Itr是AbstractList的内部类,这个类有三个成员变量
int cursor = 0; int lastRet = -1; int expectedModCount = modCount;
corsor表示游标,用于记录下一个需要被遍历到的元素的位置,lastRet记录上一个游标所在的位置,因此,他总比cursor少1,该迭代器实现如下:
public Object next(){ checkFoeComodification(); try{ Object next = get(cursor); lastRet = cursor ++; return next; }catch(IndexOutOfBoundsExcption e){ checkForComodification(); throw new NoSuchElementException(); } }
代码Object next = get(cursor);获取当前游标所指向的元素next并将游标加一,然后返回元素next,该方法可以获得下一个需要被遍历的元素,迭代器的hashNext方法实现如下;
public boolean hashNext(){ return cursor !- size(); }
只要游标的大小不等于集合的容器的容量就返回false,、否则返回true。配合每次调用next方法cursor都会加一,hashNext方法可以用于判断是否遍历完所有的集合成员,remove方法用于删除当前游标所指向的元素。。