1. 導入:なぜflatMapが重要なのか
Javaの開発現場で、入れ子構造になったデータ(例:リストの中にリストがある状態)を扱う際、ネストしたfor文で苦労した経験はありませんか?例えば、「注文リストから全注文明細を取り出す」といった処理です。flatMapを使うと、このような「1対多」の変換を1行で記述でき、コードの可読性と保守性を飛躍的に向上させることができます。
2. 基礎知識:flatMapとは何か
flatMapは、Streamの各要素を「別のStream」に変換し、最終的にそれらを一つのStreamに「平坦化(flatten)」する中間操作です。
通常のmapは「1対1」の変換ですが、flatMapは「1対多」の変換を行います。変換先のStreamが複数あっても、最終的にはそれらが連結されて一つのStreamとして出力される仕組みです。
3. 実装と解決策
flatMapを使いこなすには、変換関数が「Streamを返す」ように設計するのがポイントです。
流れとしては以下の通りです。
1. 親となるリストをStream化する。
2. flatMapメソッドに、親要素から子要素のStreamを作成する関数を渡す。
3. 最後にcollectなどで結果をまとめる。
4. サンプルプログラム
以下のコードは、複数の部署(Department)に所属する従業員(Employee)のリストから、全従業員の名前を抽出する例です。
import java.util.List;
import java.util.stream.Collectors;
import java.util.Arrays;
public class FlatMapExample {
public static void main(String[] args) {
// 部署クラスの定義(簡易版)
record Department(String name, List
List
new Department(“開発部”, Arrays.asList(“佐藤”, “鈴木”)),
new Department(“営業部”, Arrays.asList(“田中”, “高橋”))
);
// flatMapを使って、全従業員のリストを生成
List
// 部署ごとの従業員リストをStreamに変換し、それをflatMapで一つに統合
.flatMap(dept -> dept.employees().stream())
.collect(Collectors.toList());
// 結果を出力
System.out.println(“全従業員: ” + allEmployees);
}
}
5. 応用・注意点
注意点1:Nullの取り扱い
flatMapの変換関数内でnullを返すとNullPointerExceptionが発生します。リストが空の場合はnullではなく空のリストを返すように設計するか、Optionalを活用しましょう。
注意点2:パフォーマンス
非常に巨大なリストをflatMapで平坦化する場合、大量のStreamオブジェクトが生成されるため、メモリ消費に注意が必要です。また、Sequenced Collections(Java 21〜)と併用する場合、元のコレクションの順序が維持される点はメリットですが、計算量には常に意識を向けてください。
現場のヒント:
「1対多」の変換は、DBから取得したデータの加工や、JSONレスポンスの組み立てで頻出します。まずは、ネストしたループをflatMapで書き換える練習から始めてみてください。コードが格段にスッキリするはずです。

コメント