返回

Java迭代器 Spliterator: 揭秘处理并行数据的方法 (二)

Android

从Spliterator说起

Spiltor,在英文中译为“分裂者”,可细分为“split”和“iterator”。从其名称中我们可以窥探一二,Spiltor在功能设计上主要有两点:

  • 将数据源划分为多个子集合
  • 创建迭代器对象,让子集合上的元素可以按顺序获取

Spiltor的引入主要解决的问题是将各种各样的数据源(譬如集合、数组等)统一抽象为标准的数据源接口,为这些数据源提供一系列共同的功能,使我们可以方便地获取其中的数据 ,方便我们进行后续的处理。

创建Spliterator

Spiltor的创建有两种方式:

  • 通过Iterablespliterator方法获取
  • 手动实现Spliterator接口

下面我们通过代码示例了解如何实现上述两种方式:

// 通过Iterable的spliterator方法获取Spliterator
List<Integer> list = new ArrayList<>();
Spliterator<Integer> spliterator1 = list.spliterator();

// 手动实现Spliterator接口
Spliterator<Integer> spliterator2 = new Spliterator<Integer>() {
    // 返回Spliterator实例的估计大小
    @Override
    public long estimateSize() {
        return 0;
    }

    // 将Spliterator实例划分为两个或多个Spliterator实例,以支持并行处理
    @Override
    public Spliterator<Integer> trySplit() {
        return null;
    }

    // 返回Spliterator实例的下一个元素,如果没有更多元素,则返回null
    @Override
    public Integer tryAdvance(Consumer<? super Integer> action) {
        return null;
    }

    // 返回Spliterator实例的特征标志,它可以是一个组合标志,其中包含 Spliterator.ORDERED、Spliterator.DISTINCT、Spliterator.SORTED 和 Spliterator.SIZED
    @Override
    public int characteristics() {
        return 0;
    }
};

Spiltor的特征

Spliterator接口提供了一个characteristics()方法,该方法返回一个整数,代表该Spliterator具有的特征。这些特征可以通过按位运算符(|)组合起来,以表示Spliterator的多个特征。

Spliterator提供了7个特征,它们分别是:

NONE                        - 0
ORDERED                    - 1<<0
DISTINCT                    - 1<<1
SORTED                     - 1<<2
SIZED                       - 1<<3
NONNULL                     - 1<<4
IMMUTABLE                  - 1<<5
CONCURRENT                  - 1<<6

这些特征可以组合起来表示Spliterator的多个特征,例如:

Spliterator<Integer> spliterator = Arrays.asList(1, 2, 3, 4, 5).spliterator();
int characteristics = spliterator.characteristics();

if ((characteristics & Spliterator.ORDERED) != 0) {
    System.out.println("Spliterator is ordered.");
}

if ((characteristics & Spliterator.DISTINCT) != 0) {
    System.out.println("Spliterator is distinct.");
}

if ((characteristics & Spliterator.SORTED) != 0) {
    System.out.println("Spliterator is sorted.");
}

if ((characteristics & Spliterator.SIZED) != 0) {
    System.out.println("Spliterator is sized.");
}

输出:

Spliterator is ordered.
Spliterator is distinct.
Spliterator is sorted.
Spliterator is sized.

Spiltor的遍历

Spliterator提供了两种遍历方式:

  • forEachRemaining
  • tryAdvance

forEachRemaining方法接受一个Consumer函数作为参数,该函数对Spliterator的剩余元素进行操作,直到Spliterator中没有更多元素为止。该方法是最终操作,这意味着它会消耗Spliterator中的所有元素。

Spliterator<Integer> spliterator = Arrays.asList(1, 2, 3, 4, 5).spliterator();
spliterator.forEachRemaining(System.out::println);

输出:

1
2
3
4
5

tryAdvance方法接受一个Consumer函数作为参数,该函数对Spliterator中的下一个元素进行操作,如果没有更多元素,则返回false。该方法是非最终操作,这意味着它不会消耗Spliterator中的所有元素。

Spliterator<Integer> spliterator = Arrays.asList(1, 2, 3, 4, 5).spliterator();
while (spliterator.tryAdvance(System.out::println)) {
    // do something
}

输出:

1
2
3
4
5