一、迭代器概述

迭代器是一种设计模式,迭代器可以用于遍历集合,开发人员不必去了解这个集合的底层结构。迭代器封装了数据获取和预处理逻辑,屏蔽了容器的实现细节,无需暴露数据结构内部。在数据量非常庞大时使用迭代器进行数据迭代获取,避免全部取出占用过多的服务器资源,且可以对部分数据进行预加载,提升性能。本文将对 java 提供的 IteratorIterableSpliterator 三个数据迭代接口做介绍,了解其使用场景。

二、Iterator 迭代器接口

package java.util;

import java.util.function.Consumer;

public interface Iterator<E> {
    // 如果迭代有更多元素,则返回true
    boolean hasNext();

    /**
     * 返回迭代中的下一个元素
     * 如果没有元素则抛出NoSuchElementException异常
     */
    E next();

    /**
     * 从底层集合中移除此迭代器已经返回的最后一个元素,只能在next被调用后使用
     * UnsupportedOperationException – 迭代器不支持remove操作
     * IllegalStateException – 没有调用next方法或者已经执行过remove
     */
    default void remove() {
        throw new UnsupportedOperationException("remove");
    }

    // 对每个剩余元素执行给定的操作,直到处理完所有元素或操作引发异常。 
    default void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }
}

示例

MyIterator 是一个简单的迭代器示例,实现了 hasNextnext 两个方法,对 list 数组的取值逻辑进行了封装。如果数据取值非常耗时,可以非常方便的在 hasNext 进行下一列数据的预加载,能够提升性能。

class MyIterator<T> implements Iterator<T> {
    private T[] list;
    private int i;

    public MyIterator(T[] list) {
        this.list = list;
    }

    @Override
    public boolean hasNext() {
        return i < list.length;
    }

    @Override
    public T next() {
        if (!hasNext()) {
            throw new NoSuchElementException();
        }
        return list[i++];
    }
}

public class IteratorTest {
    public static void main(String[] args) {
        String[] list = new String[10];
        for (int i = 0; i < list.length; i++) {
            list[i] = String.valueOf(i);
        }
        MyIterator myIterator = new MyIterator(list);
        while (myIterator.hasNext()) {
            System.out.println(myIterator.next());
        }
    }
}

三、Iterable 迭代器接口

实现 Iterable 接口支持在增强 for 循环中进行迭代。
增强 for 中先调用 Iterable.iterator() 方法获取一个迭代器,获取到迭代器后,调用 Iterator.hasNext() 方法判断是否有后继数据,如果有后继数据,则调用 Iterator.next() 方法取得数据。

package java.lang;

import java.util.Iterator;
import java.util.Objects;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Consumer;

public interface Iterable<T> {
    /**
     * 返回T类型元素的迭代器
     */
    Iterator<T> iterator();

    /**
     * 对Iterable每个元素执行给定的操作,直到处理完所有元素或操作引发异常
     */
    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }

    /**
     * 在此Iterable描述的元素上创建一个Spliterator
     */
    default Spliterator<T> spliterator() {
        return Spliterators.spliteratorUnknownSize(iterator(), 0);
    }
}

示例

MyIterator 为上述 Iterator 示例的自定义迭代器。

class MyIterable<T> implements Iterable<T> {
    private T[] list;

    public MyIterable(T[] list) {
        this.list = list;
    }

    @Override
    public Iterator<T> iterator() {
        return new MyIterator<>(list);
    }
}

public class IteratorTest {
    public static void main(String[] args) {
        String[] list = new String[10];
        for (int i = 0; i < list.length; i++) {
            list[i] = String.valueOf(i);
        }
        Iterable<String> iterable = new MyIterable<>(list);
        for (String item : iterable) {
            System.out.println(item);
        }
        for (String item : iterable) {
            System.out.println(item);
        }
    }
}

四、Spliterator 分片迭代器接口

Spliterator 是在 JDK 1.8 中新增的迭代器,为了对并发提供支持,能够对迭代数据进行拆分、分片进行迭代。

package java.util;

import java.util.function.Consumer;
import java.util.function.DoubleConsumer;
import java.util.function.IntConsumer;
import java.util.function.LongConsumer;

public interface Spliterator<T> {
    /**
     * 如果存在剩余元素,则对其执行给定的操作,返回true;否则返回false。
     * 如果此Spliterator是ORDERED则按遇到顺序执行操作,动作抛出的异常被转发给调用者
     */
    boolean tryAdvance(Consumer<? super T> action);

    /**
     * 在当前线程中按顺序为每个剩余元素执行给定的操作,直到处理完所有元素或操作引发异常。 
     * 如果此Spliterator是ORDERED则按遇到顺序执行操作,动作抛出的异常被转发给调用者
     */
    default void forEachRemaining(Consumer<? super T> action) {
        do { } while (tryAdvance(action));
    }

    /**
     * 如果此 spliterator 可以分区,则返回一个Spliterator覆盖元素,从该方法返回时,该元素不会被此Spliterator覆盖。
     * 如果此 Spliterator 是ORDERED ,则返回的 Spliterator 必须涵盖元素的严格前缀。
     * 除非此 Spliterator 覆盖无限数量的元素,否则对trySplit()重复调用最终必须返回null 。 非空返回时:
     * 拆分前为estimateSize()报告的值,拆分后必须大于或等于estimateSize()和返回的Spliterator; 和
     * 如果这是Spliterator SUBSIZED ,然后estimateSize()此spliterator分裂之前必须等于总和estimateSize()
     * 这和分割后的返回Spliterator。
     * 此方法可能出于任何原因返回null ,包括空性、遍历开始后无法拆分、数据结构约束和效率考虑
     */
    Spliterator<T> trySplit();

    /**
     * 返回对forEachRemaining遍历将遇到的元素数量的估计,如果无限、未知或计算成本太高,则返回
     * Long.MAX_VALUE 。
     * 如果此Spliterator为SIZED且尚未部分遍历或拆分,或者此Spliterator为SUBSIZED且尚未部
     * 分遍历,则此估计必须是完整遍历将遇到的元素的准确计数。否则,此估计可能会任意地不准确,但必
     * 须按照trySplit调用之间的指定减少。
     */
    long estimateSize();

    /**
     * 如果此 Spliterator 为SIZED则返回estimateSize()便捷方法,否则返回-1
     */
    default long getExactSizeIfKnown() {
        return (characteristics() & SIZED) == 0 ? -1L : estimateSize();
    }

    /**
     * 返回此Spliterator及其元素的特征值。 结果被表示为ORDERED、DISTINCT、SORTED
     * 、SIZED、NONNULL、IMMUTABLE、CONCURRENT、SUBSIZED的或运算值
     */
    int characteristics();

    /**
     * 如果具有当前特征值返回true
     */
    default boolean hasCharacteristics(int characteristics) {
        return (characteristics() & characteristics) == characteristics;
    }

    /**
     * Spliterator包含特征值SORTED时,list是通过Comparator排序的,则返回
     * Comparator,如果Spliterator的list是自然排序的 ,则返回null
     * 特征值不是SORTED下抛错
     */
    default Comparator<? super T> getComparator() {
        throw new IllegalStateException();
    }

    /**
     * 元素定义了遇到顺序
     */
    public static final int ORDERED    = 0x00000010;

    /**
     * 对于每对遇到的元素x, y是不同的, 即!x.equals(y) 
     */
    public static final int DISTINCT   = 0x00000001;

    /**
     * 遇到顺序遵循定义的排序顺序
     */
    public static final int SORTED     = 0x00000004;

    /**
     * 在遍历或拆分之前从estimateSize()返回的值表示有限大小,在没有结构源
     * 修改的情况下,表示完整遍历将遇到的元素数量的精确计数
     */
    public static final int SIZED      = 0x00000040;

    /**
     * 遇到的元素不会为null
     */
    public static final int NONNULL    = 0x00000100;

    /**
     * 元素源不能在结构上进行修改; 即不能添加、替换或删除元素,因此在遍历过程
     * 中不会发生这种变化
     */
    public static final int IMMUTABLE  = 0x00000400;

    /**
     * 元素源可以在没有外部同步的情况下由多个线程安全地同时修改(允许添加、替换
     * 和/或删除)。 如果是这样,Spliterator 应该有一个关于遍历期间修改影响
     * 的文件化策略。
     */
    public static final int CONCURRENT = 0x00001000;

    /**
     * 由trySplit()产生的所有Spliterator都将是SIZED和SUBSIZED。
     */
    public static final int SUBSIZED = 0x00004000;

    /**
     * 专门用于原始值的Spliterator
     */
    public interface OfPrimitive<T, T_CONS, T_SPLITR extends Spliterator.OfPrimitive<T, T_CONS, T_SPLITR>>
            extends Spliterator<T> {
        @Override
        T_SPLITR trySplit();

        @SuppressWarnings("overloads")
        boolean tryAdvance(T_CONS action);

        @SuppressWarnings("overloads")
        default void forEachRemaining(T_CONS action) {
            do { } while (tryAdvance(action));
        }
    }

    /**
     * 专门用于int值的Spliterator
     */
    public interface OfInt extends OfPrimitive<Integer, IntConsumer, OfInt> {

        @Override
        OfInt trySplit();

        @Override
        boolean tryAdvance(IntConsumer action);

        @Override
        default void forEachRemaining(IntConsumer action) {
            do { } while (tryAdvance(action));
        }

        @Override
        default boolean tryAdvance(Consumer<? super Integer> action) {
            if (action instanceof IntConsumer) {
                return tryAdvance((IntConsumer) action);
            }
            else {
                if (Tripwire.ENABLED)
                    Tripwire.trip(getClass(),
                                  "{0} calling Spliterator.OfInt.tryAdvance((IntConsumer) action::accept)");
                return tryAdvance((IntConsumer) action::accept);
            }
        }

        @Override
        default void forEachRemaining(Consumer<? super Integer> action) {
            if (action instanceof IntConsumer) {
                forEachRemaining((IntConsumer) action);
            }
            else {
                if (Tripwire.ENABLED)
                    Tripwire.trip(getClass(),
                                  "{0} calling Spliterator.OfInt.forEachRemaining((IntConsumer) action::accept)");
                forEachRemaining((IntConsumer) action::accept);
            }
        }
    }

    /**
     * 专门用于long值的Spliterator
     */
    public interface OfLong extends OfPrimitive<Long, LongConsumer, OfLong> {

        @Override
        OfLong trySplit();

        @Override
        boolean tryAdvance(LongConsumer action);

        @Override
        default void forEachRemaining(LongConsumer action) {
            do { } while (tryAdvance(action));
        }

        @Override
        default boolean tryAdvance(Consumer<? super Long> action) {
            if (action instanceof LongConsumer) {
                return tryAdvance((LongConsumer) action);
            }
            else {
                if (Tripwire.ENABLED)
                    Tripwire.trip(getClass(),
                                  "{0} calling Spliterator.OfLong.tryAdvance((LongConsumer) action::accept)");
                return tryAdvance((LongConsumer) action::accept);
            }
        }

        @Override
        default void forEachRemaining(Consumer<? super Long> action) {
            if (action instanceof LongConsumer) {
                forEachRemaining((LongConsumer) action);
            }
            else {
                if (Tripwire.ENABLED)
                    Tripwire.trip(getClass(),
                                  "{0} calling Spliterator.OfLong.forEachRemaining((LongConsumer) action::accept)");
                forEachRemaining((LongConsumer) action::accept);
            }
        }
    }

    /**
     * 专门用于double值的Spliterator
     */
    public interface OfDouble extends OfPrimitive<Double, DoubleConsumer, OfDouble> {

        @Override
        OfDouble trySplit();

        @Override
        boolean tryAdvance(DoubleConsumer action);

        @Override
        default void forEachRemaining(DoubleConsumer action) {
            do { } while (tryAdvance(action));
        }

        @Override
        default boolean tryAdvance(Consumer<? super Double> action) {
            if (action instanceof DoubleConsumer) {
                return tryAdvance((DoubleConsumer) action);
            }
            else {
                if (Tripwire.ENABLED)
                    Tripwire.trip(getClass(),
                                  "{0} calling Spliterator.OfDouble.tryAdvance((DoubleConsumer) action::accept)");
                return tryAdvance((DoubleConsumer) action::accept);
            }
        }

        @Override
        default void forEachRemaining(Consumer<? super Double> action) {
            if (action instanceof DoubleConsumer) {
                forEachRemaining((DoubleConsumer) action);
            }
            else {
                if (Tripwire.ENABLED)
                    Tripwire.trip(getClass(),
                                  "{0} calling Spliterator.OfDouble.forEachRemaining((DoubleConsumer) action::accept)");
                forEachRemaining((DoubleConsumer) action::accept);
            }
        }
    }
}

示例

class MySpliterator<T> implements Spliterator<T> {
    private T[] list;
    private int index;  // 开始位置
    private int fence;  // 结束位置

    public MySpliterator(T[] list, int index, int fence) {
        this.list = list;
        this.index = index;
        this.fence = fence;
    }

    @Override
    public boolean tryAdvance(Consumer<? super T> action) {
        if (index >= fence) {
            return false;
        }
        action.accept(list[index++]);
        return index < fence;
    }

    @Override
    public Spliterator<T> trySplit() {
        int i = index;
        if (fence - i < 2) {
            return null;
        }
        int j = (index + fence)/2;
        index = j;
        return new MySpliterator<>(list, i, j);
    }

    @Override
    public long estimateSize() {
        return fence - index;
    }

    @Override
    public int characteristics() {
        return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
    }
}

public class IteratorTest {
    public static void main(String[] args) {
        String[] list = new String[10];
        for (int i = 0; i < list.length; i++) {
            list[i] = String.valueOf(i);
        }
        Spliterator<String> spliterator = new MySpliterator<>(list, 0, list.length);
        Spliterator<String> spliterator2 = spliterator.trySplit();
        new Thread(()-> spliterator.forEachRemaining(n-> System.out.println("Thread-1 = " + n))).start();
        new Thread(()-> spliterator2.forEachRemaining(n-> System.out.println("Thread-2 = " + n))).start();
    }
}