被用到炉火纯清的迭代器模式

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的迭代器源码比小编实现的复杂很多,但是基本原理无两。常常研读大神的源码有利于提升技术能力。

posted @ 2021-01-03 11:17  BUG弄潮儿  阅读(77)  评论(0编辑  收藏  举报