源码均以JDK1.8作为参考
1.定义:
Iterator提供一种方法访问一个容器对象中各个元素,而又不需要暴露对象的内部细节。
2.解析:
通用类图:
类图解析:
2.1.Iterator抽象迭代器
抽象迭代器负责定义通用的接口约定,基本都是基于JDK中Iterator接口的定义,源码如下:
public interface Iterator<E> {
boolean hasNext();
E next();
default void remove() {
throw new UnsupportedOperationException("remove");
}
/*
* @since 1.8
*/
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
基本的Iterator都会有hasNext()、next()两个方法定义的约束,remove()方法提供了在遍历时删除容器内部元素,在JDK1.8中加入了default方法forEachRemaining(Consumer action),使得在遍历时,可以指定一个action进行遍历。
2.2.Concrete Iterator具体迭代器
Concrete Iterator实现了Iterator接口,并实现了其内部的方法定义,完成具体的迭代,此时的Iterator可以用两种方式实现。
一种是ConcreteIterator持有具体容器集合的引用,迭代时遍历集合的元素,常规的Iterator都是按照此种方式实现的。
一种是ConcreteIterator作为容器集合的内部类使用,由于内部类的特殊性,可以随时获得外部类的具体实现,完成迭代操作,但是此种实现的Iterator具有依赖性,不可重复使用。
2.3.Aggregate抽象容器
Aggregate抽象容器在Iterator模式中是一个可有可无的存在,定义了容器的一些上层操作,目的是针对多个容器之间关联性的处理。
2.4.Concrete Aggregate具体容器
具体容器的实现,需要定义其内部结构等,例如ArrayList依赖数组完成元素的存取、HashMap依赖数组、链表完成元素的存取等。
3.具体应用:
上面介绍的是Iterator设计模式的通用方式,接下来根据其通用定义完成一个简单的示例,通过Iterator模式进行遍历。
3.1.Iterator抽象迭代器
此迭代器约定使用java.util.Iterator的定义。
3.2.Concrete Iterator具体迭代器
public class ConcreteIterator implements Iterator {
private Vector vector = new Vector();
// .. 定义当前游标
public int cursor = 0;
@SuppressWarnings("unchecked")
public ConcreteIterator(Vector _vector){
this.vector = _vector;
}
// .. 判断是否到达尾部
public boolean hasNext() {
if(this.cursor == this.vector.size()){
return false;
}else{
return true;
}
}
// .. 返回下一个元素
public Object next() {
Object result = null;
if(this.hasNext()){
result = this.vector.get(this.cursor++);
}else{
result = null;
}
return result;
}
// .. 删除当前元素
public boolean remove() {
this.vector.remove(this.cursor);
return true;
}
}
3.3.Aggregate抽象容器
public interface Aggregate {
// .. 是容器必然有元素的增加
public void add(Object object);
// .. 减少元素
public void remove(Object object);
// .. 由迭代器来遍历所有的元素
public Iterator iterator();
}
3.4.Concrete Aggregate具体容器
public class ConcreteAggregate implements Aggregate {
// .. 容纳对象的容器
private Vector vector = new Vector();
// .. 增加一个元素
public void add(Object object) {
this.vector.add(object);
}
// .. 返回迭代器对象
public Iterator iterator() {
return new ConcreteIterator(this.vector);
}
// .. 删除一个元素
public void remove(Object object) {
this.remove(object);
}
}
示例中ConcreteAggregate具体容器内部使用Vector作为结构实现,可以使用如下代码:
public class Test{
public static void main(String[] args){
ConcreteAggregate ca = new ConcreteAggregate();
Iterator it = ca.iterator();
while(it.hashNext()){
it.next();
}
}
}
4.forEachRemaining应用:
forEachRemaining是在JDK1.8中加入的接口的default方法,体现了JDK1.8中函数式编程思想
4.1.首先实现Consumer接口
class Action implements Consumer{
@Override
public void accept(Object o) {
// .. 自己需要处理的事情
}
}
4.2.使用Iterator实例进行迭代
ConcreteAggregate ca = new ConcreteAggregate();
Iterator it = ca.iterator();
it.forEachRemaining(new Action());
注:以上是JDK1.8提供的函数式的处理方式,在低版本的JDK中是无法完成此类操作的。
5.注意:
1.尽管Iterator模式是一个很普遍的模式,但是一般的容器都已经提供了其具体实现,除非自己进行定义和实现容器,否则Iterator是没有必要的,另外需要注意的是在很多JDK容器的实现中,
对于实现了Iterator接口的容器类,有一些实现只是附加功能,像基于简单数组实现的容器类ArrayList、Vector等,其迭代器速度要比for循环的速度慢,而对于一些基于链表实现的容器类
LinkedList等,其迭代器的速度要比for循环的速度要快,所以在应用时,需要分情况进行具体考虑。
2.对于JDK1.7中新加入的for( : )快速迭代,正式基于Iterator的,只有实现了Iterator接口,并具有相应迭代器的集合容器,才可以使用其进行处理。
3.使用Iterator设计模式的最大理由是因为利用Iterator可以跟实现分开,单独进行递增。
4.过度依赖具体类反会提高类与类的耦合度,增加零部件复用的困难。为了降低耦合度,让类作为零件再利用,必须引进抽象类和接口的概念。
注:本人是参照《设计模式之禅》和《设计模式》两本书学习所得,其中加入了自己对于Iterator设计模式的理解,以及对于JDK中源码的理解。
版权声明:本文为博主原创文章,未经博主允许不得转载。