2017-10-09 3 views
45

の理解に深くspliterator特性深くJavaのストリームとspliteratorsが、私は<strong>spliterator特性</strong>に関するいくつかの微妙な疑問を持って理解しようとするために

Q1:Stream.of()(引数なしStream.of())対Stream.empty()

  • Stream.empty()SUBSIZED、SIZED
  • Stream.of()SUBSIZED、IMMUTABLE、SIZED、

を命じStream.empty()Stream.of()の同じ特性を持っていないのはなぜ? Stream.concat()(特にORDEREDを持たない)と組み合わせて使用​​すると、影響を受けることに注意してください。私は、Stream.empty()は、は即時で、注文してはならないと言います。DISTINCTとNONNULL。また、1つだけの引数がのDISTICTを持つStream.of()の意味があります。

Q2:LongStream.of()NULL以外

を持っていないただNULL以外はLongStream.ofでは利用できないことに気づきました。 は、すべてLongStreamIntStreamおよびDoubleStreamの主な特徴ではありませんか?

Q3:LongStream.range(,)

LongStream.range(,).boxed() VS
  • LongRange.range(,)SUBSIZED不変、非NULL、サイズのORDERED、ソート
  • LongStream.range(,).boxed() DISTINCT:SIZED SUBSIZEDは、を命じ

なぜ.boxed()がこれらの特性をすべて失うのですか?それは何も失うべきではありません。

私は意味がありません... .mapToObj()がIMMUTABLEとDISTICT非NULLを、失うことができることを理解しますが、.boxed()

Q4:.peek() IMMUTABLEと非NULL

LongStream.of(1)を失う:SUBSIZED、IMMUTABLE、非NULL、SIZED、... LongStream.of(1).peek()SIZED SUBSIZED、...

なぜ.peek()がこれらの特性を失うのですか? .peekは本当に失われてはいけません。

Q5:.skip().limit()はただ、これらの操作はSUBSIZED、IMMUTABLE、非NULL、SIZED失うことに気づく

SIZED SUBSIZED、IMMUTABLE、非NULLを、失います。どうして?サイズが利用可能な場合は、最終サイズも簡単に計算できます。

Q6:.filter()がIMMUTABLE を失い、非NULL

はちょうどこの操作は、同様は、NULL以外、SIZED IMMUTABLE、SUBSIZED失うことに気づきます。 はサブスコープでサイズがですが、他の2つは意味をなさないものです。どうして?


スプライテータを深く理解している人が明快に理解できれば分かります。ありがとう。

+1

誰かが「あまりにも広すぎる」という質問を締めくくることに投票しました。私は1つで6つの質問のように見えるので、同じことをするように誘惑されました。一方、これらの詳細すべてについて全体的な説明がある可能性があります... – Nicolai

+4

@Nicolai私は最初に投票しました...しかし、それは閉鎖するのはあまりにも良いので、私はそれを再調査しました。私はこのような良い質問のために、このオールインワンが好きです。いくつかのOracleユーザー(Stuart?またはBrian?)のほかに、私はHolgerがこれらの正確な組み込み関数を知ることを期待しています。熱心に待っています。 :) – Eugene

+0

* '.mapToObj()はNONNULL、IMMUTABLE、DISTI [N] CT *を失うことがあることを理解しています。なぜソートされないのですか? – shmosel

答えて

31

特性の実際の意味を最初に見つけようとしたときに、Java 8の実装段階でその意味が明確に解決されていないと感じていて、そのために一貫して使用されていなかったことを認めなければなりません理由。

Spliterator.IMMUTABLE検討:

元素源が構造的に修飾することができないことを意味

特性値。つまり、要素を追加、置換、または削除できないため、このような変更はトラバーサル中には発生しません。

それはList配列かといえば、その結果、配列を受け入れストリームとspliterator工場(そのクローン化されていない)レポート際、通常は構造的な変更とはみなされていない、このリストに「置き換え」を参照して奇妙ですIMMUTABLELongStream.of(…)またはArrays.spliterator(long[])などです。

我々はもっと寛大に「クライアントによる限り観察できない」としてこれを解釈する場合は、CONCURRENTに有意な差は一部の要素がかどうかを認識するためにどのような方法なしでクライアントに報告されるいずれかの場合のように、存在しません彼らは巡回中に追加されたか、または除去のために報告されなかったものがあるかどうかは、スプライテータを巻き戻して比較する方法がないためです。

仕様は継続:トラバーサル中に検出構造干渉に関する(ConcurrentModificationExceptionを投げるなど)文書のポリシーを有することが期待されるIMMUTABLE又はCONCURRENT報告しない

A Spliteratorを。

そして、それだけで、関連するもの、のいずれかの報告spliterator、IMMUTABLEまたはCONCURRENTだ、ConcurrentModificationExceptionを投げたことがないことが保証されます。もちろん、CONCURRENTは意味的にSIZEDを排除しますが、それはクライアントコードには影響しません。

実際、これらの特性はStream API内で使用されていないため、一貫性のない使用は決してどこかに気づかれません。

これもすべての中間操作がCONCURRENTIMMUTABLENONNULL特性をクリアする効果を持っている理由の説明です:ストリームの実装では、それらを維持していない彼らとストリームの状態を表す、内部クラスを使用していません。特定のストリームのためのそれの不在は効果がありませんので、


同様に、NONNULLは、どこでも使用されていません。返さspliteratorは常に特性SIZEDSUBSIZEDを報告

:私は
Spliterators.spliterator​(long[] array, int fromIndex, int toIndex, int additionalCharacteristics)に委譲Arrays.spliterator(long[], int, int)の内部使用までLongStream.of(…)問題を追跡することができます。発呼者は、スプライテータが報告する追加の特性を提供することができる。 (たとえば、配列がそれ以上変更されないことがわかっている場合はIMMUTABLEと指定し、配列データに出会いの順序があると見なされる場合はORDEREDを指定します)。代わりに、SIZEDSUBSIZEDIMMUTABLE、およびORDEREDを報告するスプライテータを返す、Arrays.spliterator(long[], int, int)メソッドを代わりに使用することができます。

IMMUTABLEの特性が一貫していないことに注意してください。 Arrays.spliteratorArrays.streamLongStream.of(…)は、指定してもという特性を報告しますが、発信者が変更を加えないように保証することはできません。アレイ。配列を構造的に変更することはできないため、要素を構造的な変更ではなく、別の意味を持たないようにすることを考慮しない限り、もう一度無意味になります。

そして明らかに、NONNULLの特性が指定されていません。プリミティブ値はnullではなく、Spliterator.Abstract<Primitive>Spliteratorクラスは必ずNONNULLという特性を注入しますが、Spliterators.spliterator​(long[],int,int,int)が返すスプライテータはSpliterator.AbstractLongSpliteratorから継承しません。

悪いことは、仕様を変更せずに修正できないということですが、良いことはとにかく結果がないことです。


我々は何の影響を持っていないCONCURRENTIMMUTABLE、またはNONNULLを持つすべての問題を、無視するのであれば、我々は

SIZEDskip & limitを持っています。これはよく知られた問題です。skiplimitがStream APIによって実装されています。他の実装も想像できる。これは、予測可能なサイズを持つ必要がありますが、現行の実装を前提とした無限ストリームとlimitの組み合わせにも当てはまります。

Stream.concat(…)Stream.empty()との組み合わせ。空のストリームがではないことが妥当と思われます。は結果の順序に制約を課します。しかし、Stream.concat(…)の1つの入力だけが順序を持たないときに順序を解放するという振る舞いは疑わしい。順序に関してあまりにも積極的であることは新しいことではないことに注意してください。this Q&Aは、意図的に最初に考えられた動作について説明していますが、Java 8のアップデート60以降で修正されています。おそらく、Stream.concatは、 ...

.boxed()の動作は説明が簡単です。 .mapToObj(Long::valueOf)のように純粋に実装されている場合、結果はまだソートされているか別個であると仮定することができないので、すべての知識が失われます。しかし、これはJava 9で修正されました。そこで、LongStream.range(0,10).boxed()SUBSIZED|SIZED|ORDERED|SORTED|DISTINCTの特性を持ち、実装に関連するすべての特性を維持します。

+0

ありがとう@Holger。それは維持されていない非常に多くの特性を持って少し厄介です。しかし、大半の人が*英語の人に見える*(ポルトガル語の表現では、それはただのショーのためだけです)、それほど問題はありません。私は問題のある問題は 'Stream.concat'を' Stream.empty'と一緒に使うことに同意しました。もう1つは、「制限」または「スキップ」のある未定義のストリームです。これについては、https://stackoverflow.com/questions/27547519/most-efficient-way-to-get-the-last-element-ofで議論されています。 -a-stream/46562493#46562493 – Tet

+0

@Holger真剣に、これはもう一度、私が何度も再利用され、再リンクされる素晴らしい答えです。絶対に素晴らしい! – Eugene

関連する問題