1. 導入:なぜcollectが必要なのか?
Javaでプログラミングをしていると、「リストの中の特定のデータを抽出して、新しいリストやマップにまとめたい」という場面によく遭遇します。これまでのJavaでは、for文とif文を組み合わせて空のリストを作成し、一つずつ要素を追加していく必要がありました。
しかし、Java 8から導入されたStream APIのcollectメソッドを使えば、これらの複雑な処理をたった1行で、かつ宣言的に記述できます。コードがスッキリするだけでなく、バグの混入も減らせるため、現代のJava開発では必須のスキルです。
2. 基礎知識:collectメソッドとは?
collectメソッドは、Streamの要素を別のデータ構造(List、Set、Mapなど)に「集約(変換)」するための操作です。
ここで重要なのがCollectorというインターフェースです。これは「どのように集約するか」というルールを定義したもので、Javaが標準で用意しているCollectorsクラスを使うことで、簡単に目的の変換を行えます。
・Listに変換:Collectors.toList()
・Setに変換:Collectors.toSet()
・Mapに変換:Collectors.toMap()
これらを使うことで、ストリームという「流れ」の状態にあるデータを、私たちが扱いやすい「コレクション」という形に固めることができます。
3. 実装:具体的にどう書くのか?
基本的な使い方は「ストリームを作る」→「中間操作(filterやmap)」→「collectで集約」という流れです。例えば、「数字のリストから偶数だけを取り出し、新しいListにする」といった処理が、非常に直感的に記述できます。
4. サンプルプログラム
以下のコードをコピーして、ご自身の環境で実行してみてください。
import java.util.;
import java.util.stream.Collectors;
public class CollectExample {
public static void main(String[] args) {
// 元となるデータのリスト
List fruits = Arrays.asList("apple", "banana", "cherry", "apricot", "blueberry");
// 1. リストへの集約: 'a'から始まるフルーツだけを取り出す
List aList = fruits.stream()
.filter(s -> s.startsWith("a"))
.collect(Collectors.toList());
System.out.println("Aで始まるリスト: " + aList);
// 2. マップへの集約: フルーツ名をキー、その文字数を値にする
Map fruitMap = fruits.stream()
.collect(Collectors.toMap(
name -> name, // キー
name -> name.length() // 値
));
System.out.println("マップへの変換: " + fruitMap);
}
}
5. 応用・注意点:現場でハマりやすいポイント
注意点1:toMapの重複キー
Collectors.toMapを使う際、キーが重複すると「IllegalStateException」が発生してプログラムが落ちます。実務では、重複が発生しそうな場合は、第3引数にマージ関数(値がぶつかった時にどうするか)を指定するようにしましょう。
注意点2:不変コレクションの扱い
Java 16以降であれば、Collectors.toList()の代わりにCollectors.toUnmodifiableList()を使うと、後から変更できない「不変リスト」を作成できます。予期せぬデータの書き換えを防ぐため、可能な限りこちらの利用を検討してください。
最後に
collectは、データ処理の「仕上げ」を担う非常に強力なツールです。まずはCollectors.toList()から使い始め、徐々にtoMapなどの複雑な変換に慣れていくのが、シニアエンジニアへの近道です。ぜひ試してみてください。

コメント