迭代器模式(Iterator Pattern)
概念
迭代器模式是一种行为型设计模式,它用于提供一种顺序访问聚合对象(如集合、列表、数组)元素的方式,而无需暴露该对象的内部表示。迭代器模式将遍历行为从集合对象中分离出来,通过提供统一的接口来访问不同聚合对象中的元素。
应用场景
-
遍历集合对象:在系统中需要遍历不同类型的集合(如列表、栈、队列)时,迭代器模式可以提供一致的方式来遍历,而不必了解集合的内部结构。
-
封装集合的内部结构:迭代器隐藏了集合的具体实现细节,用户不需要关心集合的内部实现,例如数组的长度、链表的节点等,避免了直接操作集合对象。
-
解耦集合与算法:通过将遍历算法与集合本身分离,用户可以独立定义不同的迭代器,满足特定的遍历需求,如正序遍历、倒序遍历、跳步遍历等。
注意点
-
并发修改问题:当集合在遍历过程中被修改(如新增或删除元素),可能会引发并发修改异常,需要特别注意在多线程场景下的使用。
-
迭代器失效问题:一些容器在迭代时,如果容器内部结构改变(比如删除了一个元素),默认的迭代器会失效并抛出异常。
-
内存管理:如果集合特别大且占用大量内存,使用迭代器遍历时应考虑如何管理内存,例如在遍历过程中是否需要保持所有元素在内存中。
核心要素
-
Iterator(迭代器接口):定义访问和遍历元素的方法,例如
next()
和hasNext()
。 -
ConcreteIterator(具体迭代器):具体的迭代器实现,实现迭代器接口并维护遍历状态。
-
Aggregate(聚合对象接口):定义创建迭代器的接口,用于返回具体的迭代器对象。
-
ConcreteAggregate(具体聚合对象):具体的集合类,实现创建迭代器的接口,并负责存储对象。
Java代码完整示例
代码示例:简单的迭代器模式实现
import java.util.ArrayList;
import java.util.List;// 迭代器接口
interface Iterator<T> {boolean hasNext();T next();
}// 聚合对象接口
interface Aggregate<T> {Iterator<T> createIterator();
}// 具体迭代器实现
class ConcreteIterator<T> implements Iterator<T> {private List<T> items;private int position = 0;public ConcreteIterator(List<T> items) {this.items = items;}@Overridepublic boolean hasNext() {return position < items.size();}@Overridepublic T next() {return items.get(position++);}
}// 具体聚合对象实现
class ConcreteAggregate<T> implements Aggregate<T> {private List<T> items = new ArrayList<>();public void addItem(T item) {items.add(item);}@Overridepublic Iterator<T> createIterator() {return new ConcreteIterator<>(items);}
}// 客户端代码
public class IteratorPatternDemo {public static void main(String[] args) {ConcreteAggregate<String> aggregate = new ConcreteAggregate<>();aggregate.addItem("Item 1");aggregate.addItem("Item 2");aggregate.addItem("Item 3");Iterator<String> iterator = aggregate.createIterator();while (iterator.hasNext()) {System.out.println(iterator.next());}}
}
输出结果:
Item 1
Item 2
Item 3
各种变形用法完整示例
-
倒序迭代器
有时需要反向遍历集合,这时可以通过实现倒序迭代器来实现。代码示例:倒序迭代器
class ReverseIterator<T> implements Iterator<T> {private List<T> items;private int position;public ReverseIterator(List<T> items) {this.items = items;this.position = items.size() - 1;}@Overridepublic boolean hasNext() {return position >= 0;}@Overridepublic T next() {return items.get(position--);} }public class ReverseIteratorPatternDemo {public static void main(String[] args) {ConcreteAggregate<String> aggregate = new ConcreteAggregate<>();aggregate.addItem("Item 1");aggregate.addItem("Item 2");aggregate.addItem("Item 3");Iterator<String> reverseIterator = new ReverseIterator<>(aggregate.createIterator().items);while (reverseIterator.hasNext()) {System.out.println(reverseIterator.next());}} }
输出结果:
Item 3 Item 2 Item 1
-
迭代器失效和并发修改异常
当集合在迭代过程中发生变化时,通常会抛出ConcurrentModificationException
异常,尤其在使用Java自带的集合类时需要特别注意。代码示例:并发修改异常
import java.util.ArrayList; import java.util.Iterator; import java.util.List;public class ConcurrentModificationDemo {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("Item 1");list.add("Item 2");list.add("Item 3");Iterator<String> iterator = list.iterator();while (iterator.hasNext()) {String item = iterator.next();System.out.println(item);// 在迭代过程中修改集合,抛出异常if ("Item 2".equals(item)) {list.remove(item);}}} }
输出结果:
Item 1 Item 2 Exception in thread "main" java.util.ConcurrentModificationException
-
自定义迭代器与泛型支持
迭代器模式可以通过泛型来实现对不同类型的集合进行遍历。代码示例:自定义泛型迭代器
class GenericAggregate<T> implements Aggregate<T> {private List<T> items = new ArrayList<>();public void addItem(T item) {items.add(item);}@Overridepublic Iterator<T> createIterator() {return new ConcreteIterator<>(items);} }public class GenericIteratorPatternDemo {public static void main(String[] args) {GenericAggregate<Integer> intAggregate = new GenericAggregate<>();intAggregate.addItem(1);intAggregate.addItem(2);intAggregate.addItem(3);Iterator<Integer> intIterator = intAggregate.createIterator();while (intIterator.hasNext()) {System.out.println(intIterator.next());}GenericAggregate<String> stringAggregate = new GenericAggregate<>();stringAggregate.addItem("Item A");stringAggregate.addItem("Item B");Iterator<String> stringIterator = stringAggregate.createIterator();while (stringIterator.hasNext()) {System.out.println(stringIterator.next());}} }
输出结果:
1 2 3 Item A Item B
-
内部类实现迭代器
Java标准库中的集合类,如ArrayList
等,通常通过内部类实现自己的迭代器。代码示例:内部类实现迭代器
class MyCollection<T> {private List<T> items = new ArrayList<>();public void addItem(T item) {items.add(item);}public Iterator<T> iterator() {return new MyIterator();}private class MyIterator implements Iterator<T> {private int index = 0;@Overridepublic boolean hasNext() {return index < items.size();}@Overridepublic T next() {return items.get(index++);}} }public class InnerClassIteratorDemo {public static void main(String[] args) {MyCollection<String> collection = new MyCollection<>();collection.addItem("Item X");collection.addItem("Item Y");Iterator<String> iterator = collection.iterator();while (iterator.hasNext()) {System.out.println(iterator.next());}} }
输出结果:
Item X Item Y
总结
迭代器模式通过提供统一的遍历接口,隐藏了聚合对象的内部结构,使得代码能够适应多种不同的集合类型。在实际开发中,Java标准库已经内置了大量的迭代器实现(如List
、Set
等),我们可以直接使用或扩展这些实现,来满足不同的需求。