Javaストリームとスプリッターを深く理解するために、スプリッターの特性について微妙な質問があります:
Q1:Stream.empty()
vs Stream.of()
(Stream.of()引数なし)
Stream.empty()
: SUBSIZED、SIZED Stream.of()
: SUBSIZED、[〜#〜] immutable [〜#〜]、SIZED、[ 〜#〜]順序付け[〜#〜]Stream.empty()
にStream.of()
と同じ特性がないのはなぜですか? Stream.concat()と組み合わせて使用すると影響があることに注意してください(特にORDERED
がない場合)。 Stream.empty()
には IMMUTABLEとORDERED だけでなく、 DISTINCTとNONNULL も必要です。また、 [〜#〜] distict [〜#〜] を持つ1つの引数のみでStream.of()
も意味があります。
Q2:LongStream.of()
に [〜#〜] nonnull [〜#〜] がありません
NONNULLは_LongStream.of
_では使用できないことに注意してください。 NONNULL
はすべてのLongStream
s、IntStream
sおよびDoubleStream
sの主な特徴ではありませんか?
Q3:LongStream.range(,)
vs LongStream.range(,).boxed()
LongRange.range(,)
: SUBSIZED、IMMUTABLE、NONNULL、SIZED、ORDERED、SORTED、DISTINCTLongStream.range(,).boxed()
: SUBSIZED、SIZED、ORDERED なぜ.boxed()
はこれらすべての特性を失うのですか?それは何も失うべきではありません。
.mapToObj()
は NONNULL、IMMUTABLEおよびDISTICT を失う可能性があることを理解していますが、.boxed()
...は意味がありません。
Q4:.peek()
は IMMUTABLEおよびNONNULL を失います
LongStream.of(1)
: SUBSIZED、IMMUTABLE、NONNULL、SIZED、... LongStream.of(1).peek()
: SUBSIZED、SIZED、.. .
なぜ.peek()
はこれらの特性を失うのですか? _.peek
_が実際に失われることはありません。
Q5:.skip()
、.limit()
は SUBSIZED、IMMUTABLE、NONNULL、SIZED を失います
これらの操作では SUBSIZED、IMMUTABLE、NONNULL、SIZED が失われることに注意してください。どうして?サイズが利用可能な場合は、最終的なサイズも簡単に計算できます。
Q6:.filter()
は IMMUTABLE、NONNULL を失います
この操作では、 SUBSIZED、IMMUTABLE、NONNULL、SIZED も失われることに注意してください。 SUBSIZEDとSIZED を失うことは理にかなっていますが、他の2つは意味がありません。どうして?
スプリッターを深く理解している誰かがいくつかの明確さをもたらすことができれば私は感謝します。ありがとう。
私は特性の実際の意味を最初に見つけようとしたときにも困難があったことを認めざるを得ません。また、その意味はJava 8の実装フェーズでは明確に解決されておらず、そのため一貫して使用されていないと感じていました。
Spliterator.IMMUTABLE
を検討してください:
要素のソースを構造的に変更できないことを示す特性値。つまり、要素を追加、置換、または削除できないため、トラバーサル中にこのような変更を行うことはできません。
このリストで「置き換え」が見られるのは奇妙です。これは、List
または配列と言えば、通常は構造変更とは見なされず、その結果、配列(クローンではない)を受け入れるストリームおよびスプリッターファクトリーレポートIMMUTABLE
、LongStream.of(…)
またはArrays.spliterator(long[])
など。
これを「クライアントが監視できない限り」とより寛大に解釈した場合、CONCURRENT
に大きな違いはありません。どちらの場合もsome要素はクライアントに報告されず、それらが走査中に追加されたかどうか、または一部が削除のために報告されなかったかどうかを認識する方法。スプリッターを巻き戻して比較する方法がないためです。
仕様は続きます:
IMMUTABLE
またはCONCURRENT
を報告しないSpliteratorには、トラバーサル中に検出された構造的干渉に関する文書化されたポリシー(たとえば、ConcurrentModificationException
のスロー)が必要です。
そして、これが唯一の関連事項であり、IMMUTABLE
またはCONCURRENT
のいずれかがスプリテレーターを報告し、ConcurrentModificationException
をスローしないことが保証されています。もちろん、CONCURRENT
は意味的にSIZED
を排除しますが、これはクライアントコードに影響を与えません。
実際、これらの特性はStream APIでは何にも使用されていないため、一貫性のない使用はどこかで気付かれることはありません。
every中間操作がCONCURRENT
、IMMUTABLE
およびNONNULL
の特性をクリアする効果がある理由もこれです。Stream実装はそれらを使用せず、ストリームの状態を表す内部クラスはそれらを維持しません。
同様に、NONNULL
はどこでも使用されないため、特定のストリームが存在しない場合は効果がありません。 LongStream.of(…)
の問題を、デリゲートするArrays.spliterator(long[], int, int)
の内部使用まで追跡できますSpliterators.spliterator(long[] array, int fromIndex, int toIndex, int additionalCharacteristics)
:
返されたスプリッターは常に特性
SIZED
およびSUBSIZED
を報告します。呼び出し元は、スプリテレーターが報告する追加の特性を提供できます。 (たとえば、配列がそれ以上変更されないことがわかっている場合は、IMMUTABLE
を指定します。配列データが遭遇順序を持つと見なされる場合は、ORDERED
を指定します)。代わりにメソッドArrays.spliterator(long[], int, int)
を使用できます。これは、SIZED
、SUBSIZED
、IMMUTABLE
、およびORDERED
を報告するスプリッターを返します。
(繰り返しますが)IMMUTABLE
特性の一貫性のない使用に注意してください。変更がないことを保証する必要があるように再び扱われますが、Arrays.spliterator
、そしてArrays.stream
とLongStream.of(…)
は、仕様によっても、[[SOME_VARIABLE] _特性を報告できますが、呼び出し元が配列を変更しないことを保証します。要素を構造的変更ではないように設定することを検討しない限り、配列は構造的に変更できないため、全体の区別は再び無意味になります。
そして、IMMUTABLE
characteristicを明確に指定していません。プリミティブ値をNONNULL
にできないことは明らかであり、Spliterator.Abstract<Primitive>Spliterator
クラスは常にnull
特性を注入しますが、Spliterators.spliterator(long[],int,int,int)
によって返されるスプリッターはSpliterator.AbstractLongSpliterator
から継承しません。
悪い点は、仕様を変更せずにこれを修正できないことです。良い点は、とにかく影響がないことです。
したがって、結果のないNONNULL
、CONCURRENT
、またはIMMUTABLE
の問題を無視すると、
NONNULL
およびSIZED
&skip
。これはよく知られている問題で、limit
およびskip
がStream APIによって実装された方法の結果です。他の実装も考えられます。これは、無限のストリームとlimit
の組み合わせにも適用されます。limit
は予測可能なサイズでなければなりませんが、現在の実装ではそうではありません。
Stream.concat(…)
とStream.empty()
の組み合わせ。空のストリームがnotを実行することは結果の順序に制約を課すことは理にかなっているようです。ただし、Stream.concat(…)
の1つの入力だけに順序がない場合に順序を解放する動作には疑問があります。順序付けに関してあまりにも積極的であることは新しいことではないことに注意してください。最初は意図的であると見なされていたが、Javaまで修正された動作については this Q&A を参照してください8、更新60。おそらく、Stream.concat
もこの時点で議論されているはずです…
.boxed()
の動作は簡単に説明できます。 .mapToObj(Long::valueOf)
のように単純に実装されている場合、mapToObj
は結果がまだソートまたは区別されているとは想定できないため、すべての知識が失われます。しかし、これはJava 9で修正されています。LongStream.range(0,10).boxed()
にはSUBSIZED|SIZED|ORDERED|SORTED|DISTINCT
の特性があり、実装に関連するすべての特性を維持しています。