Spliterator接口重点
- Spliterator接口是迭代器Iterator改版,只不过Spliterator可以并行的遍历元素,但是Spliterator不是线程安全的,并行的关键在于 trySplit方法,可以将一个Spliterator拆分为两个Spliterator,每个Spliterator元素不一样,两个Spliterator合起来才是所有的元素,迭代器 Iterator 源码可以看我这篇文章 Iterator
- Spliterator使用tryAdvance迭代元素并进行一些操作,使用estimateSize获取改Spliterator中剩余可迭代的元素个数
- Spliterator接口有一个重要的属性就是特征,可以通过characteristics获取其特征,其特征有ORDERED, DISTINCT,SORTED, SIZED, NONNULL,IMMUTABLE, CONCURRENT, SUBSIZED这些特征代表Spliterator里面的元素特征,如SORTED,表示分离器里面的元素是有序的,IMMUTABLE表示分离器中的元素是不可变
Spliterator特征值
| 特征值 | 意义 |
|---|
| ORDERED | 分离器内部元素是按插入顺序排序的,如List |
| DISTINCT | 分离器内部元素是不重复的,如Set |
| SORTED | 分离器内部元素是有序的,如SortedSet |
| SIZED | 表示分离器在遍历或拆分之前从estimateSize()返回的值表示有限大小,大多数集合有这个特性 |
| NONNULL | 分离器内部元素是非null的 |
| IMMUTABLE | 分离器内部元素是不可变的 |
| CONCURREN | 分离器内部元素是可以被多个线程安全地同时修改,而无需外部同步 |
| SUBSIZED | 表示分离器是被拆分出来的 |
Spliterator接口方法
| 方法名 | 作用 |
|---|
| boolean tryAdvance(Consumer action) | 如果存在剩余元素,则对其执行给定操作,并返回true,不存在剩余元素返回false |
| Spliterator trySplit() | 如果此拆分器可以拆分,则返回一个包含元素的拆分器, 从该方法返回后,该拆分器将不包含这些拆分出去的元素 |
| long estimateSize() | 返回forEachRemaining遍历将遇到的元素数的估计值, 如果无限、未知或计算成本太高,则返回Long#MAX_VALUE |
| int characteristics() | 返回此拆分器及其元素的特征 |
Consumer 是一个函数式接口,里面只有一个accept方法,表示接收一个值处理后并返回一个值,Consumer源码可以看我这篇文章 Consumer
Spliterator接口默认方法
| 方法名 | 作用 |
|---|
| default void forEachRemaining(Consumer action) | 在当前线程中按顺序对每个剩余元素执行给定操作, 直到处理完所有元素或该操作引发异常为止,循环调用tryAdvance方法 |
| default Comparator getComparator() | 此拆分器的特征是SORTED,则返回Comparator,如果是自然排序,返回null,如果特征是其他抛出异常 |
| default long getExactSizeIfKnown() | 如果此拆分器的特征是SIZED,则执行estimateSize()并返回其返回值, 否则返回-1 |
| default boolean hasCharacteristics(int characteristics) | 如果此拆分器的characteristics包含所有给定的特征,则返回true |
Spliterator接口源码
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 {
boolean tryAdvance(Consumer super T> action);
default void forEachRemaining(Consumer super T> action) {
do { } while (tryAdvance(action));
}
Spliterator trySplit();
long estimateSize();
default long getExactSizeIfKnown() {
return (characteristics() & SIZED) == 0 ? -1L : estimateSize();
}
int characteristics();
default boolean hasCharacteristics(int characteristics) {
return (characteristics() & characteristics) == characteristics;
}
default Comparator super T> getComparator() {
throw new IllegalStateException();
}
public static final int ORDERED = 0x00000010;
public static final int DISTINCT = 0x00000001;
public static final int SORTED = 0x00000004;
public static final int SIZED = 0x00000040;
public static final int NonNULL = 0x00000100;
public static final int IMMUTABLE = 0x00000400;
public static final int ConCURRENT = 0x00001000;
public static final int SUBSIZED = 0x00004000;
public interface OfPrimitive>
extends Spliterator {
@Override
T_SPLITR trySplit();
@SuppressWarnings("overloads")
boolean tryAdvance(T_CONS action);
@SuppressWarnings("overloads")
default void forEachRemaining(T_CONS action) {
do { } while (tryAdvance(action));
}
}
public interface OfInt extends OfPrimitive {
@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);
}
}
}
public interface OfLong extends OfPrimitive {
@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);
}
}
}
public interface OfDouble extends OfPrimitive {
@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);
}
}
}
}