一、概述
1.1 什么是迭代器模式?
迭代器模式(Iterator Pattern)是一种行为型设计模式,它提供一种有效的方法来访问和遍历一个聚合对象中的各个元素,而又不需要暴露聚合对象的内部表示。
迭代器模式通常会在需要遍历一系列对象的时候使用,例如遍历一个列表或集合等。通过使用迭代器模式,我们可以在不暴露对象内部细节的情况下,方便的对集合对象进行访问和遍历。
1.2 迭代器模式的作用和优势
迭代器模式的主要作用在于解耦了遍历算法和集合对象之间的关系,这意味着可以对集合对象进行各种操作,而不必关心它的内部数据结构和遍历方式。以下是迭代器模式的优势:
- 简化遍历过程:迭代器模式为遍历不同类型的聚合对象提供了共同的接口,简化了遍历过程,增加了灵活性。
- 支持多种遍历方式:迭代器模式使得可以定义多种方式来遍历同一种聚合对象,例如正向遍历、反向遍历等。
- 分离遍历算法和聚合对象:迭代器模式将遍历算法与聚合对象分离开来,所以改变聚合对象的内部结构对算法没有影响。
- 统一遍历接口:迭代器模式定义了统一的遍历接口,使得用户能够方便地遍历不同的聚合对象。
- 灵活性和扩展性:聚合对象和迭代器对象有独立的变化空间,可以扩展新的聚合对象和迭代器,使得系统更加灵活性和可扩展性。
1.3 迭代器模式的实现机制
迭代器模式主要由以下两个部分组成:
- 迭代器(Iterator):定义访问和遍历聚合对象的接口,支持单向或双向遍历。
- 聚合对象(Aggregate):定义创建迭代器对象的接口,通常包含一个返回迭代器对象的方法。 迭代器模式的实现机制可以通过以下三种方式来实现:
- 传统方式的迭代器模式:定义迭代器接口,实现迭代器对象,并对聚合对象进行迭代器的实现。
- JDK内置迭代器:使用Java的内置迭代器类实现迭代器模式,比如ArrayList的Iterator。
- Java 8 的Stream API:使用Stream的foreach()方法对集合进行遍历,而不是传统的for、while循环。
二、迭代器模式的角色
2.1 迭代器模式的参与者
迭代器模式中包含以下两个参与者:
- 迭代器(Iterator):定义访问和遍历聚合对象的接口。
- 聚合对象(Aggregate):定义返回一个迭代器对象的接口,通常由具体的聚合对象实现。
2.2 迭代器模式中的三个重要角色
除了迭代器和聚合对象之外,迭代器模式中还包含一个重要的角色——具体聚合对象(ConcreteAggregate)。
具体聚合对象(ConcreteAggregate):具体聚合对象实现了聚合对象(Aggregate)接口,它拥有一个迭代器工厂方法,也就是实现了创建迭代器对象的方法,该方法返回一个对应的具体迭代器对象。同时,具体聚合对象也可以向外部提供聚合对象的元素,但是它不需要关心或确定遍历的顺序,具体迭代器来负责管理迭代过程中的顺序。 具体聚合对象中有个创建迭代器对象的方法,可以通过该方法创建具体迭代器对象,并且该具体迭代器可以访问具体聚合对象的元素,实现了遍历的功能。同时,具体迭代器还确定了遍历的接口和遍历的顺序。
三、迭代器模式的实现方式
3.1 传统的迭代器模式实现方式
在传统的迭代器模式实现方式中,我们需要先定义一个迭代器接口(Iterator),然后在具体聚合对象(ConcreteAggragate)中实现该接口,同时可以定义一个具体迭代器类(ConcreteIterator)来实现具体的遍历过程。示例代码如下:
// 迭代器接口 interface Iterator<T> { boolean hasNext(); T next(); } // 具体聚合对象 class ConcreteAggregate<T> implements Iterable<T> { private List<T> items = new ArrayList<>(); public void add(T item) { items.add(item); } public Iterator<T> iterator() { return new ConcreteIterator<T>(this); } public int size() { return items.size(); } public T get(int index) { return items.get(index); } } // 具体迭代器 class ConcreteIterator<T> implements Iterator<T> { private ConcreteAggregate<T> aggregate; private int index; public ConcreteIterator(ConcreteAggregate<T> aggregate) { this.aggregate = aggregate; this.index = 0; } public boolean hasNext() { return index < aggregate.size(); } public T next() { return aggregate.get(index++); } }
在上述代码中,迭代器接口(Iterator)定义了两个方法,其中 hasNext() 用于判断是否还有下一个元素,next() 方法用于获取下一个元素。
具体聚合对象(ConcreteAggregate)实现了 Java 标准库中的 Iterable 接口,定义了 iterator() 方法来返回一个具体迭代器对象(ConcreteIterator),并且可以通过其他方法来提供具体元素的访问。
具体迭代器(ConcreteIterator)通过聚合关系引用到具体聚合对象(ConcreteAggregate),并且记录当前访问聚合对象中哪个元素,实现了迭代器接口中的两个方法。
3.2 JDK内置迭代器实现方式
Java SDK已经为我们提供了一些内置的迭代器,可以用于遍历集合类(例如List、Set和Map)中的元素。下面我们来介绍一些常用的内置迭代器。
3.2.1 ListIterator
ListIterator是在Iterator接口的基础上增加了一些方法而产生的。ListIterator可以用于遍历List集合,也可以修改List集合中的元素。
ListIterator有以下几个重要的方法:
- boolean hasNext():判断是否还有下一个元素。
- Object next():返回下一个元素。
- boolean hasPrevious():判断是否还有上一个元素。
- Object previous():返回上一个元素。
- int nextIndex():返回下一个元素的索引。
- int previousIndex():返回上一个元素的索引。
- void add(Object obj):添加元素。
- void set(Object obj):修改当前元素。
- void remove():删除元素。
下面是一个ListIterator的示例代码:
List<String> list = new ArrayList<>(); list.add("A"); list.add("B"); list.add("C"); ListIterator<String> iterator = list.listIterator(); while(iterator.hasNext()){ System.out.println(iterator.next()); } System.out.println("反向遍历:"); while(iterator.hasPrevious()){ System.out.println(iterator.previous()); }
执行结果为:
A B C 反向遍历: C B A