2017-09-06 11 views
3

私のフィルタが真実になった後、私のストリームを一度だけ反復させる方法はありますか?Javaストリーム。一度だけ

例:

list.stream() 
    .filter(ele -> ele.isBlue()) 
    .map(Element::getSomething) 
    .collect(toList()); 

は、私は私のリストの多くの要素を持っていると言うが、一つだけは青です。そして私はただ一つが青色であることを知っていますが、私はどこにいるのか分かりません。そして議論のために、isBlue()は遅いメソッドなので、一度ヒットすると停止したいと言うことができます。

+5

'collect'を呼び出す代わりに、findFirst()。orElse(null)'を呼び出します。 'parallelStream'を使用していて、ストリームに要素が1つしかないことが保証されている場合は、' findAny()。orElse(null) 'を代わりに使うことができます。 – Lothar

+2

ストリームは怠惰なので、 'filter(..)。findFirst().Else(..whatever)' –

答えて

7

あなたの代わりにcollect()使用findFirst()/findAny()の、一つだけの要素を探しているなら。

Optional<Something> s = list.stream() 
    .filter(ele -> ele.isBlue()) 
    .map(Element::getSomething) 
    .findAny(); 

あなたは、単一の青色の要素、または空Optionalを含むOptionalを取得するのいずれか。 (確定findFirst()返す最初の要素、及びfindAny()それが見つかった単一の適切な要素が返される場合)

は、並列処理が含まれている場合にのみ、単純なストリームでfindFirst()findAny()間には違いありません。

5

あなたはまだcollect、しかしlimitと可能性:

list.stream() 
    .filter(ele -> ele.isBlue()) 
    .map(Element::getSomething) 
    .limit(1) 
    .collect(toList()); 
+2

これは、コレクションを必要とする追加の作業を行う場合に便利です。手動で新しいリストに「オプション」を追加します。 – Kayaman

+0

チップをありがとう!私は最初にfindFirst()バリアントを試してみたいと思います。 – Kims

+3

@Kayaman:しかし、 'findFirst()。map(Collections :: singletonList).orElseGet(Collections :: emptyList)'はあまり複雑ではなく、いくつかの素敵なプロパティを持っています... – Holger

3

それは、ストリームパイプラインが最後のステップ、終了操作によって駆動されていることを理解する価値があります。

代わりのコンベアベルトの下のアイテムをプッシュストリームプロデューサーの思考は、待機消費者に、アイテムを引っ張って終了操作を考える - 尋ねられたときプロデューサーが新しいアイテムを追加します。

例では、終了操作はcollect(collector)です。これは、前のステップからアイテムがなくなるまでアイテムをプルし、各要素をコレクタに送信します。前のステップでmap()ですが、それはオンデマンドで動作します - それは唯一のその前段階からアイテムを引っ張る - filter()からcollect()は別の項目を要求したとき。

findFirst()は、別の終了操作です。前の手順でストリームの最初の項目である1つの項目を尋ねます。だから我々はfindFirst()パイプラインステップは、正確に一度map()ステップから読み込みます...

list.stream() 
    .filter(ele -> ele.isBlue()) 
    .map(Element::getSomething) 
    .findFirst(toList()); 

...にあなたの例を変更した場合。アイテムを取得すると、Optional.of(item)が返されます。順番に

map()は正確に一度filter()から読み込みます。 filter()isBlue()がtrueになるまでストリームから繰り返し読み込み、それを返します。

filter()が一致するものを見つけずに入力ストリームの最後に到達すると、ストリームの終わりを示します。これはパイプラインを伝播し、findFirst()はストリームの終わりに気付き、Optional.empty()を返します。

も任意一致する項目が返されfindAny()があります。これは、パイプラインの一部が並列化された場合に速く戻る場合があります。または、パイプラインが順序敏感なステップを持つと並列化される可能性があります。

すべての終了操作を確認するには、Stream Javadocを参照してください。