数値が0のときに、ストリームでlimit(number)呼び出しをスキップするにはどうすればよいですか?


19

のオブジェクトを提供するJavaコードがいくつかありますitems。それはに基づいてそれらを制限しますmaxNumber

items.stream()
     .map(this::myMapper)
     .filter(item -> item != null)
     .limit(maxNumber)
     .collect(Collectors.toList());

それは正しく動作しますが、問題はこれです:制限をスキップする方法はありmaxNumber == 0ますか?

私はこれを行うことができることを知っています:

if (maxNumber == 0) {
    items.stream()
         .map(this::myMapper)
         .filter(item -> item != null)
         .collect(Collectors.toList());
} else {
    items.stream()
         .map(this::myMapper)
         .filter(item -> item != null)
         .limit(maxNumber)
         .collect(Collectors.toList());
}

しかし、おそらくもっと良い方法があると思いますか?

回答:


15

たぶん

.limit(maxNumber == 0 ? Long.MAX_VALUE : maxNumber)

2 ^ 63-1以上の要素を持つストリームに取り組む可能性は非常に低いので、トリックを実行します...

少なくとも、これに関する並列ストリームには注意してください... APIドキュメントのメモには次のように書かれています:

APIの注limit()通常、シーケンシャルストリームパイプラインでは安価な操作ですが、特にmaxSizeの値が大きい場合、順序付けされた並列パイプラインでは非常に高価になる可能性があります。


はい、それでうまくいきました、ありがとう!
randomuser1

20

いいえ、ストリームパイプラインではパイプラインの一部を実際にスキップすることはできないため、ステップ内の条件付きロジックを使用limit()して、パイプラインにalways を含めるか、ストリームを部分的に構築する必要があります。問題のif / elseよりも少し読みやすい(IMHO)

Stream<Item> s = items.stream()
         .map(this::myMapper)
         .filter(Objects::nonNull);

if(maxNumber > 0) {
    s = s.limit(maxNumber);
}

List<Item> l = s.collect(Collectors.toList());

このような単純なケースではそれほど大きな違いはありませんが、通常のコードコレクションがメソッドを介して渡され、ストリームに変換されてからコレクションに戻されることがよくあります。このような場合は、本当に必要になるまで、ストリームを部分的に操作する方がよいでしょうcollect()

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.