在上篇文章中,已经使用int数组简单说明了java 8中Spliterator的使用,上篇文章还有以下几个问题还没有解决:
-
Arrays类使用的spliterator具体实现由哪些 - 以上具体实现中Consumer有哪些类型
- 集合是否提供了Spliterator操作
具体实现
如上图所示,Arrays的spliterator函数提供了4中参数类型,对应不同的参数,底层有4中实现。参数类型为T时,底层的实现为ArraySpliterator;参数类型为int时,底层实现为IntArraySpliterator;参数类型为long时,底层实现为LongArraySpliterator;参数类型为double时,底层实现为DoubleArraySpliterator。
上图为4种底层实现类的继承结构。
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));
}
}
使用泛型参数,顶层接口Spliterator.OfPrimitive仅仅声明了了trySplit和tryAdvance方法,并提供了forEachRemaining方法的默认实现。ArraySpliterator是比较特殊的,它底层存储的是Object类型的数组,并且直接实现了Spliterator接口。相较于Spliterator.OfPrimitive接口,Spliterator接口需要子类实现的方法包括trySplit,tryAdvance, estimateSize()。Spliterator接口和Spliterator.OfPrimitive接口的最大区别就是Spliterator接口是为了分割迭代Object类型数组,Spliterator.OfPrimitive接口是为了分割迭代int, long,double类型数组。
Consumer
Arrays提供了4中参数类型的spliterator函数,实现原理是一样,但是在执行tryAdvance和forEachRemaining时传递的Consumer类型不一样,对应于Arrays勒种4中不同的Spliterator,java 8提供了四种类型的Consumer:
- Consumer
- IntConsumer
- LongConsumer
- DoubleConsumer
Consumer针对的数据类型为Object;IntConsumer, LongConsumer, DoubleConsumer分别针对数据类型int, long, double。以上四种Consumer接口都申明了accept方法,并提供了andThen的默认框架实现。
集合的分割迭代
public interface Iterable<T> {
Iterator<T> iterator();
/**
* @since 1.8
*/
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
/**
* @since 1.8
*/
default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}
Iterable接口是集合类的顶层接口,从java 8开始,Iterable增加了spliterator和forEach方法,故所有的Iterable具体实现都可以使用spliterator方法进行分割迭代。由于集合内部存储的基本类型的数据都会被自动装箱,故forEach方法的参数是接收Object类型的Consumer。