JDK 8ソースのSpliteratorは並行してシーズマリーを巡回します.
21872 ワード
スピリットは何ですか?
Spliter内部構造
デリバティブインターフェースOf Primitive
スピリット類の中にこのようなインターフェースが見えますが、このインターフェースは何をしていますか?
Spliterator.OfIntの実現
Spliterators類では、int[]データに対してディケンサを分割することができました.アラーリストと同じです.ですから、次は簡単に読むだけです.
public interface Spliterator {
Spliteratorは分割可能なシーズマリーで、iteratorと順番にシーズマリーを巡回して見ることができます.jdk 1.8が発表された後、並列処理の能力が大幅に増強されました.Spliterは並行エルゴードのために設計されたローズマリーで、jdk 1.8のセットフレームの中のデータ構造はデフォルトでspliter atorを実現しました.後はArayListのspliteratorと一緒に解析します.Spliter内部構造
// , true, false
boolean tryAdvance(Consumer super T> action);
// , , 。 tryAdvance
default void forEachRemaining(Consumer super T> action) {
do { } while (tryAdvance(action));
}
// , Spliterator
Spliterator trySplit();
//
long estimateSize();
// SIZED , ; -1
default long getExactSizeIfKnown() {
return (characteristics() & SIZED) == 0 ? -1L : estimateSize();
}
//
int characteristics();
//
default boolean hasCharacteristics(int characteristics) {
return (characteristics() & characteristics) == characteristics;
}
// Spliterator list Comparator , Comparator
// Spliterator list , null
//
default Comparator super T> getComparator() {
throw new IllegalStateException();
}
特徴値とは、このSpliterがどのような特性を持っているかを示すために、Spliteratorの使用をよりよく制御し、最適化することができます.コンパレータのgetCompratorを取得する方法については、まだ具体的に使われているところを見ていませんので、多少の誤差があるかもしれません.特徴値は以下の通りです. //
public static final int ORDERED = 0x00000010;
//
public static final int DISTINCT = 0x00000001;
//
public static final int SORTED = 0x00000004;
//
public static final int SIZED = 0x00000040;
// null
public static final int NONNULL = 0x00000100;
public static final int IMMUTABLE = 0x00000400;
public static final int CONCURRENT = 0x00001000;
public static final int SUBSIZED = 0x00004000;
ArayListSpliterstatic final class ArrayListSpliterator<E> implements Spliterator<E> {
// ArrayList
private final ArrayList list;
// ( ),advance/split
private int index;
// ( ),-1
private int fence;
// list modCount
private int expectedModCount;
ArrayListSpliterator(ArrayList list, int origin, int fence,
int expectedModCount) {
this.list = list;
this.index = origin;
this.fence = fence;
this.expectedModCount = expectedModCount;
}
// ( : fence expectedModCount )
private int getFence() {
int hi;
ArrayList lst;
//fence<0 ( ,fence 0):
if ((hi = fence) < 0) {
//list null ,fence=0
if ((lst = list) == null)
hi = fence = 0;
else {
// ,fence = list 。
expectedModCount = lst.modCount;
hi = fence = lst.size;
}
}
return hi;
}
// list, spliterator
public ArrayListSpliterator trySplit() {
//hi
//lo
//
int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
// lo>=mid, , null
// lo
return (lo >= mid) ? null :
new ArrayListSpliterator(list, lo, index = mid, expectedModCount);
}
// true ,
// false , 。。。
public boolean tryAdvance(Consumer super E> action) {
if (action == null)
throw new NullPointerException();
//hi
//i
int hi = getFence(), i = index;
//
if (i < hi) {
// i ,index+1
index = i + 1;
@SuppressWarnings("unchecked") E e = (E)list.elementData[i];
action.accept(e);
// , ,
if (list.modCount != expectedModCount)
throw new ConcurrentModificationException();
return true;
}
return false;
}
//
public void forEachRemaining(Consumer super E> action) {
int i, hi, mc; // hoist accesses and checks from loop
ArrayList lst; Object[] a;
if (action == null)
throw new NullPointerException();
if ((lst = list) != null && (a = lst.elementData) != null) {
// fence<0 , fence expectedModCount , getFence(), ?
if ((hi = fence) < 0) {
mc = lst.modCount;
hi = lst.size;
}
else
mc = expectedModCount;
if ((i = index) >= 0 && (index = hi) <= a.length) {
for (; i < hi; ++i) {
@SuppressWarnings("unchecked") E e = (E) a[i];
// action.accept
action.accept(e);
}
//
if (lst.modCount == mc)
return;
}
}
throw new ConcurrentModificationException();
}
public long estimateSize() {
return (long) (getFence() - index);
}
public int characteristics() {
// :、 size
return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
}
}
テストコードは以下の通りです. List arrs = new ArrayList<>();
arrs.add("a");
arrs.add("b");
arrs.add("c");
arrs.add("d");
arrs.add("e");
arrs.add("f");
arrs.add("h");
arrs.add("i");
arrs.add("j");
Spliterator a = arrs.spliterator();
// :a:0-9(index-fence)
Spliterator b = a.trySplit();
// :b:4-9,a:0-4
Spliterator c = a.trySplit();
// :c:4-6,b:4-9,a:6-9
Spliterator d = a.trySplit();
// :d:6-7,c:4-6,b:4-9,a:7-9
分割するたびに残りの前半を分割し、fenceは変わらず、indexは後にシフトします.また、1.ArayList Spliterは本質的には元のlistを操作し、indexとfenceだけで処理範囲を制御しています.また、ArayList Spliterは要素を遍歴する時に、listを構造変更操作できなくなります.デリバティブインターフェースOf Primitive
スピリット類の中にこのようなインターフェースが見えますが、このインターフェースは何をしていますか?
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));
}
}
このインターフェースは基本的に変更されていません.これは複数の一般的な声明を追加しただけです.本質的にはSpliterと大きな違いはありません.ただし、tryAdvanceのパラメータactionタイプを制限しています.CONSとtrySplitの戻りパラメータT_SPLITRは、インターフェースを実装する際に、タイプを先に宣言しなければならない.OfPrimitiveインターフェースに基づいて、またOfInt、OfLong、OfDoubleなどを派生して、もっぱらint、Long、doubleなどを処理するために用います.Spliterator.OfIntの実現
Spliterators類では、int[]データに対してディケンサを分割することができました.アラーリストと同じです.ですから、次は簡単に読むだけです.
// ArrayList ,array , 。
static final class IntArraySpliterator implements Spliterator.OfInt {
private final int[] array;
private int index;
private final int fence;
//
private final int characteristics;
//
public IntArraySpliterator(int[] array, int additionalCharacteristics) {
this(array, 0, array.length, additionalCharacteristics);
}
public IntArraySpliterator(int[] array, int origin, int fence, int additionalCharacteristics) {
this.array = array;
this.index = origin;
this.fence = fence;
this.characteristics = additionalCharacteristics | Spliterator.SIZED | Spliterator.SUBSIZED;
}
@Override
public OfInt trySplit() {
// , ,
int lo = index, mid = (lo + fence) >>> 1;
return (lo >= mid)
? null
: new IntArraySpliterator(array, lo, index = mid, characteristics);
}
@Override
public void forEachRemaining(IntConsumer action) {
int[] a; int i, hi; // hoist accesses and checks from loop
if (action == null)
throw new NullPointerException();
if ((a = array).length >= (hi = fence) &&
(i = index) >= 0 && i < (index = hi)) {
do { action.accept(a[i]); } while (++i < hi);
}
}
@Override
public boolean tryAdvance(IntConsumer action) {
if (action == null)
throw new NullPointerException();
if (index >= 0 && index < fence) {
action.accept(array[index++]);
return true;
}
return false;
}
@Override
public long estimateSize() { return (long)(fence - index); }
@Override
public int characteristics() {
return characteristics;
}
@Override
public Comparator super Integer> getComparator() {
if (hasCharacteristics(Spliterator.SORTED))
return null;
throw new IllegalStateException();
}
}