Spliterator是Java 8中加入的另一个新接口;这个名字代表“可分迭代器”(splitableiterator)。和Iterator一样,Spliterator也用于遍历数据源中的元素,但它是为了并行执行而设计的。

自定义Spliterator需要实现Spliterator接口。

Spliterator接口

public interface Spliterator<T> {
    boolean tryAdvance(Consumer<? super T> action);
    Spliterator<T> trySplit();
    long estimateSize();
    int characteristics();
}
  • T:Spliterator遍历的元素的类型
  • tryAdvance:类似于普通的Iterator,因为它会按顺序一个一个使用Spliterator中的元素,并且如果还有其他元素要遍历就返回true。
  • trySplit:把一些元素划出去分给第二个Spliterator(由该方法返回),让它们两个并行处理。
  • estimateSize:估计还剩下多少元素要遍历,让拆分均匀一点。
  • characteristics

特 性

含 义

ORDERED

元素有既定的顺序(例如List),因此Spliterator在遍历和划分时也会遵循这一顺序

DISTINCT

对于任意一对遍历过的元素x和y,x.equals(y)返回false

SORTED

遍历的元素按照一个预定义的顺序排序

SIZED

该Spliterator由一个已知大小的源建立(例如Set),因此estimatedSize()返回的是准确值

NONNULL

保证遍历的元素不会为null

IMMUTABLE

Spliterator的数据源不能修改。这意味着在遍历时不能添加、删除或修改任何元素

CONCURRENT

该Spliterator的数据源可以被其他线程同时修改而无需同步

SUBSIZED

该Spliterator和所有从它拆分出来的Spliterator都是SIZED

拆分过程

【java8】自定义Spliterator_collector

自定义

package com.morris.java8.parallel;

import java.util.Spliterator;
import java.util.function.Consumer;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

public class IntSpliterator implements Spliterator<Integer> {

    private int start;

    private int end;

    private int current;

    private int[] data;

    public Stream<Integer> stream() {
       return StreamSupport.stream(this, false);
    }

    public Stream<Integer> parallelStream() {
        return StreamSupport.stream(this, true);
    }

    public IntSpliterator(int[] data) {
        this(0, data.length, data);
    }

    public IntSpliterator(int start, int end, int[] data) {
        this.start = start;
        this.end = end;
        this.current = start;
        this.data = data;
    }

    @Override
    public boolean tryAdvance(Consumer<? super Integer> action) {

        if(current < end) {
            action.accept(data[current++]);
            return true;
        }
        return false;
    }

    @Override
    public Spliterator<Integer> trySplit() {

        if(start - end <= 2) {
            return null;
        }

        int mid=start+((end-start)/2);
        int newStart=mid;
        int newEnd=end;
        end=mid;
        return new IntSpliterator(newStart, newEnd, data);

    }

    @Override
    public long estimateSize() {
        return data.length - end;
    }

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

    public static void main(String[] args) {
        int[] ints = IntStream.rangeClosed(1, 10).toArray();
        IntSpliterator intSpliterator = new IntSpliterator(ints);

        intSpliterator.stream().forEach(System.out::println);
        //intSpliterator.parallelStream().forEach(System.out::print);

    }

}