在上篇文章中,已经使用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
。