Java入門:Collection.stream().forEach()とCollection.forEach()の違いを徹底解説
Javaのコレクションを反復処理する方法として、Collection.stream().forEach()とCollection.forEach()の2つがよく使われます。一見似ているこの2つのメソッドですが、内部の仕組みや動作には重要な違いがあります。
Collection.forEach() の特徴
Collection.forEach() は、コレクション自身が持つイテレータを使用して反復処理を行います。
多くのコレクションでは、反復処理中の構造的な変更(要素の追加・削除)は許可されていません。反復中に要素を追加または削除すると、ConcurrentModificationException(並行変更例外)が即座にスローされます。
また、同期化された(synchronized)コレクションに対して反復処理を行う場合、コレクションのセグメントをロックし、すべての呼び出しにわたってそのロックを保持し続けます。
Collection.stream().forEach() の特徴
Collection.stream().forEach() もコレクションの反復処理に使用できますが、まずコレクションをストリームに変換し、そのストリームに対して反復処理を行うという点が異なります。そのため、処理の順序は保証されません。
例外の扱いについても同様に、反復中に構造的な変更が発生した場合は ConcurrentModificationException がスローされますが、検出されるタイミングが Collection.forEach() と異なる場合があります。
両者の違いの比較表
| 番号 | 項目 | Collection.forEach() | Collection.stream().forEach() |
|---|---|---|---|
| 1 | 基本動作 | コレクション自身のイテレータを使用する | コレクションを一旦ストリームに変換してから反復処理する |
| 2 | 処理順序 | Iterableで順序が定義されている場合、常にその反復順序で実行される | 処理順序は未定義 |
| 3 | ロック | 同期化されたコレクションの場合、コレクションをロックし、全呼び出しにわたって保持する | コレクションをロックしない |
| 4 | 例外 | 構造的な変更が発生した場合、即座に例外をスローする | 例外は後からスローされる可能性がある |
Collection.stream().forEach() のサンプルコード
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("Ram");
list.add("TutorialPoints");
// ストリームに変換してから反復処理
list.stream().forEach(System.out::print);
}
}Collection.forEach() のサンプルコード
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("Ram");
list.add("TutorialPoints");
// イテレータを使って直接反復処理
list.forEach(System.out::print);
}
}まとめ
単純な反復処理であれば Collection.forEach() が直感的で、順序も保証されます。一方、フィルタリングやマッピングなどの中間操作を組み合わせたい場合は、stream().forEach() を使うことで Stream API の豊富な機能を活用できます。用途に応じて適切な方を選択することが重要です。
-
JavaのIteratorとEnumerationの違いを徹底比較!使い分けのポイントを解説
はじめに:IteratorとEnumerationとはJavaのコレクションフレームワークには、コレクション内の要素を順番に走査(トラバース)しながらアクセスするための仕組みとして「カーソル」が用意されています。その代表格が Iterator(イテレータ) と Enumeration(列挙) の2つです。両者はどちらもコレクションフレームワークに属しますが、登場した時期と役割が異なります。EnumerationはJDK 1.0から存在する歴史あるインターフェースで、IteratorはJDK 1.2でコレクションフレームワークとともに導入された、より新しいインターフェースです。Enumerati
-
JavaでのArrayListとHashSetの違いを徹底解説!使い分けのポイントも紹介
HashSetとArrayListは、どちらもJavaコレクションフレームワークにおいて最も重要なクラスの一つです。それぞれ特徴が異なるため、用途に応じた適切な使い分けが求められます。本記事では、ArrayListとHashSetの主な違いを6つの観点から比較し、実際のサンプルコードとともにわかりやすく解説します。ArrayListとHashSetの違い一覧No.項目ArrayListHashSet1実装インターフェースListインターフェースを実装しています。Setインターフェースを実装しています。2内部構造内部的には配列(動的配列)を使って実装されています。内部的にはHashMapを使って