What
迭代器模式(Iterator Design Pattern),提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部表示。该模式用来遍历集合对象。这里说的“集合对象”也可以叫“容器”“聚合对象”,实际上就是包含一组对象的对象,比如数组、链表、树、图、跳表。迭代器模式将集合对象的遍历操作从集合类中拆分出来,放到迭代器类中,让两者的职责更加单一。
Why
迭代器模式有以下几个优点:
- 它支持以不同的方式遍历一个聚合对象。
- 迭代器简化了聚合类。
- 在同一个聚合上可以有多个遍历。
- 在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码。
When
开篇的时候我们就讲了,迭代器模式适用于遍历一个聚合对象时使用。
How
一个完整的迭代器模式,一般会涉及容器和容器迭代器两部分内容。为了达到基于接口而非实现编程的目的,容器又包含容器接口、容器实现类,迭代器又包含迭代器接口、迭代器实现类。容器中需要定义 iterator() 方法,用来创建迭代器。迭代器接口中需要定义 hasNext()、currentItem()、next() 三个最基本的方法。容器对象通过依赖注入传递到迭代器类中。
我们知道,线性数据结构包括数组和链表,在大部分编程语言中都有对应的类来封装这两种数据结构,在开发中直接拿来用就可以了。假设在这种新的编程语言中,这两个数据结构分别对应 ArrayList 和 LinkedList 两个类。除此之外,我们从两个类中抽象出公共的接口,定义为 List 接口,以方便开发者基于接口而非实现编程,编写的代码能在两种数据存储结构之间灵活切换。现在,我们针对 ArrayList 和 LinkedList 两个线性容器,设计实现对应的迭代器。我们定义一个迭代器接口 Iterator,以及针对两种容器的具体的迭代器实现类 ArrayIterator 和 ListIterator。
具体代码如下:
public interface List<E> {
Iterator<E> iterator();
void add(E element);
void remove(int index);
E get(int index);
int length();
}
public class ArrayList<E> implements List<E> {
private Object[] array;
private static final Integer DEFAULT_LENGTH = 10;
private int len;
public ArrayList() {
array = new Object[DEFAULT_LENGTH];
len = 0;
}
@Override
public Iterator<E> iterator() {
return new ArrayIterator<>(this);
}
@Override
public void add(E element) {
array[len++] = element;
}
@Override
public void remove(int index) {
int numMoved = len - index - 1;
if (numMoved > 0)
System.arraycopy(array, index + 1, array, index,
numMoved);
array[--len] = null;
}
@Override
public E get(int index) {
return (E) array[index];
}
@Override
public int length() {
return this.len;
}
}
public interface Iterator<E> {
boolean hasNext();
void next();
E currentItem();
}
public class ArrayIterator<E> implements Iterator<E> {
private int cursor;
private ArrayList<E> arrayList;
public ArrayIterator(ArrayList<E> arrayList) {
this.arrayList = arrayList;
}
@Override
public boolean hasNext() {
return cursor < arrayList.length();
}
@Override
public void next() {
cursor++;
}
@Override
public E currentItem() {
return arrayList.get(cursor);
}
}
限于篇幅,这里给出的ArrayList的实现非常简单,甚至有些边界条件都没有处理,有兴趣的话,大家可以去看下java.util.ArrayList的实现。
测试类如下:
public class TestMain {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
Iterator iterator = list.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.currentItem());
iterator.next();
}
list.remove(0);
iterator = list.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.currentItem());
iterator.next();
}
}
}
输出如下:
1
2
3
2
3
代码地址
写在最后
如果你觉得我写的文章帮到了你,欢迎点赞、评论、分享、赞赏哦,你们的鼓励是我不断创作的动力~