被用到炉火纯清的迭代器模式
0x01:迭代器模式简介
Java中可以说已经把迭代器模式用到了极致,每一个集合类都关联了一个迭代器类Iterator。
迭代器模式(Iterator),提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示。UML类图如下:
其中,Aggregate是聚集抽象类,负责提供创建具体迭代器角色的接口;Iterator是迭代抽象类,用于定义得到开始对象、得到下一个对象、判断是否到结尾、当前对象等抽象方法,统一接口;ConcreteAggregate是具体聚集类,继承Aggregate;ConcreteIterator是具体迭代器类,继承Iterator,实现开始、下一个、是否结尾、当前对象等方法。具体角色说明:
-
Iterator(迭代器):迭代器定义访问和遍历元素的接口;
-
ConcreteIterator (具体迭代器):具体迭代器实现迭代器接口,对该聚合遍历时跟踪当前位置;
-
Aggregate (聚合):聚合定义创建相应迭代器对象的接口;
-
ConcreteAggregate (具体聚合):具体聚合实现创建相应迭代器的接口,该操作返回ConcreteIterator的一个适当的实例;
0x02:迭代器模式实现
抽象聚合:负责提供接口,比如定义一个类似createIterator()这样的方法,在Java集合类里一般是iterator()方法。
public interface Aggregate {
public void add(Object object);
public void remove(Object object);
public Iterator iterator();
}
抽象迭代器:负责定义访问和遍历元素的接口,基本上有固定的三个方法,即first()获取第一个元素、next()访问下一个元素、hasNext()判断已经遍历到最后。
public interface Iterator {
public Object next(); //遍历到下一个元素
public boolean hasNext(); //是否已经遍历到尾部
public boolean remove(); //删除当前指向的元素
}
具体聚合
public class ConcreteAggregate implements Aggregate {
private List list = new ArrayList();
@Override
public void add(Object object) {
this.list.add(object);
}
public void remove(Object object) {
this.list.remove(object);
}
@Override
public Iterator iterator() {
return new ConcreteIterator(this.list);
}
}
具体迭代器:简单的实现就是通过一个游标,在一个容器中前后移动,遍历所有它需要查看的元素
public class ConcreteIterator implements Iterator {
private List list= new ArrayList();
public int cursor = 0; //定义当前游标
public ConcreteIterator(List list) {
this.list= list;
}
@Override
public Object next() {
Object result = null;
if (this.hasNext()) {
result = this.list.get(this.cursor);
this.cursor = this.cursor + 1;
} else {
result = null;
}
return result;
}
@Override
public boolean hasNext() {
if (this.cursor == this.list.size()) {
return false;
}
return true;
}
@Override
public boolean remove() {
this.list.remove(this.cursor);
return true;
}
}
迭代器模式测试代码
注意引入自己定义的Iterator类,而不是Java内部封装好的java.util.Iterator类。
public class Client {
public static void main(String[] args) {
Aggregate aggregate = new ConcreteAggregate();
aggregate.add("java乐园");
aggregate.add("架构师知音");
aggregate.add("非常架构");
//遍历
Iterator iterator = aggregate.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
0x03:JDK中的迭代器源码分析
在JDK涉及到的迭代器Iterator都与集合有关,主要相关实现在java.util包下。下面以 ArrayList 为例进行分析:
java.lang.Iterable类:表示一个可以被迭代的对象
public interface Iterable<T> {
Iterator<T> iterator();
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}
java.util.Iterator:表示抽象迭代器
public interface Iterator<E> {
boolean hasNext();
E next();
default void remove() {
throw new UnsupportedOperationException("remove");
}
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
java.util.Collection:表示抽象聚合对象
public interface Collection<E> extends Iterable<E> {
Iterator<E> iterator();
boolean add(E e);
boolean remove(Object o);
boolean addAll(Collection<? extends E> c);
boolean removeAll(Collection<?> c);
//其他省略
.......
}
java.util.AbstractList.Itr:具体迭代器实现类,该类是 java.util.AbstractList 类的一个内部类
private class ListItr extends Itr implements ListIterator<E> {
//具体代码省略
.......
}
java.util.ArrayList:具体聚合对象
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
//具体代码省略
.......
}
java.util.ArrayList整体实现UML类图
[来源:https://www.alicharles.com/article/design-pattern/jdk-iterator-pattern/]
研读JDK源码的迭代器模式,可以非常有效的学习和理解迭代器模式。从代码上看JDK的迭代器源码比小编实现的复杂很多,但是基本原理无两。常常研读大神的源码有利于提升技术能力。