私の理解では、Java 8 は、やStream
などのターミナル操作が実行されると消費されたと見なされます。forEach()
count()
multipleFilters_separate
ただし、以下のテスト ケースでは、遅延中間操作であるIllegalStateException
にもかかわらずfilter
、2 つのステートメントとして呼び出され、エラーが発生します。それでも、2 つのフィルター操作を 1 つのステートメントに連結して動作させることができます。
@Test(expected=IllegalStateException.class)
public void multipleFilters_separate() {
Stream<Double> ints = Stream.of(1.1, 2.2, 3.3);
ints.filter(d -> d > 1.3);
ints.filter(d -> d > 2.3).forEach(System.out::println);
}
@Test
public void multipleFilters_piped() {
Stream<Double> ints = Stream.of(1.1, 2.2, 3.3);
ints.filter(d -> d > 1.3)
.filter(d -> d > 2.3)
.forEach(System.out::println);
}
このことから、Stream
そのステートメントがターミナル操作を呼び出すかどうかに関係なく、 はそれを使用する最初のステートメントの後で消費されるものと想定しています。これは正しいでしょうか?
ベストアンサー1
ターミナル操作が実行されると、消費されたとみなされます。ただし、 javadocに記載されているStream
ように、複数の中間操作が同じインスタンスに対して実行されることは想定されていません。Stream
Stream
ストリームは一度だけ操作される(中間または終端ストリーム操作を呼び出す)これにより、たとえば、同じソースが 2 つ以上のパイプラインにフィードされる「フォークされた」ストリームや、同じストリームの複数のトラバーサルが除外されます。ストリーム実装は、ストリームが再利用されていることを検出すると、IllegalStateException をスローすることがあります。ただし、一部のストリーム操作では、新しいストリーム オブジェクトではなくレシーバーが返される場合があるため、すべてのケースで再利用を検出できるとは限りません。
中間ストリーム操作の場合は、Stream
前の操作によって返された次の操作を呼び出す必要があります。
public void multipleFilters_separate() {
Stream<Double> ints = Stream.of(1.1, 2.2, 3.3);
ints = ints.filter(d -> d > 1.3);
ints.filter(d -> d > 2.3).forEach(System.out::println);
}