Java ストリームで flatMap() 後の filter() が完全に遅延しない理由
Java ストリームでは、filter() は遅延とみなされますこれは、すぐに実行されるのではなく、消費の時点で実行されることを意味します。ただし、filter() が flatMap() の後に続く場合、その動作は真の怠惰から逸脱します。
デモ
次のコードを考えてみましょう:
Stream.of(1, 2, 3) .filter(i -> { System.out.println(i); return true; }) .findFirst() .get();
この例では、filter() が整数のストリームに適用されます。出力は、遅延評価で予想されるように、フィルター関数が最初の要素に対してのみ呼び出されることを示しています。
1 Result: 1
ただし、次のコードでは:
Stream.of(1, 2, 3) .flatMap(i -> Stream.of(i - 1, i, i + 1)) .flatMap(i -> Stream.of(i - 1, i, i + 1)) .filter(i -> { System.out.println(i); return true; }) .findFirst() .get();
フィルター( ) 関数は、2 つの flatMap() 操作を適用することによって生成されたストリームに適用されます。平坦化されたストリームの最初の要素がフィルター条件を満たしているにもかかわらず、フィルター関数は残りの要素に対して引き続き呼び出されます。
-1 0 1 0 1 2 1 2 3 Result: -1
説明
この動作の理由は、 flatMap() が元のストリームの要素ごとに新しいストリームを作成するためです。 filter() は遅延操作のままですが、平坦化操作は早期終了をサポートしません。したがって、平坦化プロセスが開始されると、ストリームの後半でフィルター条件が満たされた場合でも、中断することはできません。
影響
この動作により、予期せぬ事態が発生する可能性があります。特に無限ストリームを扱う場合には、その結果が大きくなります。たとえば、 flatMap() オペレーションの入力ストリームが無限の場合、一致する要素が見つからないことが保証されているにもかかわらず、filter() オペレーションはその関数の適用を無期限に試行します。
JDK の修正
ここで説明されている問題は Java 10 で解決されました (および Java 8 にバックポートされました)。これらのバージョンでは、 flatMap() は早期終了をサポートするように最適化されており、 flatMap() に従うかどうかに関係なく、filter() およびその他の遅延操作の動作が一貫したままであることが保証されます。
以上がJava Streams で ` flatMap() ` の後の `filter()` が常に遅延しないのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。