Collection.stream().forEach() と Collection.forEach() の違いは何ですか? 質問する

Collection.stream().forEach() と Collection.forEach() の違いは何ですか? 質問する

.stream()を使用すると、 や のようなチェーン操作を使用して並列ストリームを使用できることは理解しています.filter()。 しかし、小さな操作 (たとえば、リストの要素を印刷する) を実行する必要がある場合、それらの違いは何ですか?

collection.stream().forEach(System.out::println);
collection.forEach(System.out::println);

ベストアンサー1

図のような単純なケースでは、ほとんど同じです。ただし、重要な微妙な違いがいくつかあります。

1 つの問題は順序付けに関するものです。 ではStream.forEach、順序は未定義です。 順次ストリームでは発生しそうにありませんが、 がStream.forEach任意の順序で実行されることは の仕様の範囲内です。 これは並列ストリームでは頻繁に発生します。 対照的に、 は、が指定されている場合Iterable.forEach、常に の反復順序で実行されますIterable

もう一つの問題は副作用です。 で指定されたアクションは非干渉でStream.forEachある必要があります。(java.util.stream パッケージのドキュメント) はIterable.forEach潜在的に制約が少ないです。 のコレクションについてはjava.utilIterable.forEachは通常そのコレクションの を使用しますIterator。そのほとんどは、失敗を早くするそして、反復中にコレクションの構造が変更されると例外が発生しますConcurrentModificationException。ただし、反復中に構造的ではない変更は許可されます。たとえば、ArrayList クラスのドキュメントは、「要素の値を設定するだけでは構造の変更にはなりません」と述べています。したがって、 for アクションは問題なくArrayList.forEach基になる値を設定できます。ArrayList

並行コレクションはまたもや異なります。フェイルファストではなく、弱い一貫性完全な定義は、そのリンクにあります。ただし、簡単に について考えてみましょう。そのメソッドConcurrentLinkedDequeに渡されるアクションは、基礎となる deque を構造的に変更することができ、スローされることはありません。ただし、発生する変更は、この反復処理で表示される場合と表示されない場合があります。(したがって、「弱い」一貫性です。)forEachConcurrentModificationException

同期コレクションを反復処理する場合、さらに別の違いが見られますIterable.forEach。このようなコレクションでは、Iterable.forEach コレクションのロックを取得する一度だけ実行し、アクション メソッドのすべての呼び出しにわたって保持します。Stream.forEach呼び出しでは、ロックしないコレクションのスプリッテレータを使用します。これは、非干渉の一般的なルールに依存します。ストリームをサポートするコレクションは、反復処理中に変更される可能性があり、変更された場合、またはConcurrentModificationException一貫性のない動作が発生する可能性があります。

おすすめ記事