【完全入門】Java Stream API の flatMap を世界一わかりやすく解説|map との違い・実践例・初心者がつまずくポイントを徹底整理

Java

はじめに:なぜ flatMap を覚えるべきなのか?

Java の Stream API を学ぶと、必ずぶつかるものがあります。それが flatMap です。

「map はなんとなくわかったけど、flatMap は急に難しくなる…」
「なんで List の中の List を扱うときに flatMap を使うの?」

こんな声をよく聞きます。

でも実は、flatMap が苦手なのは 概念を理解できていないだけ です。
仕組みがわかれば、あなたの Java コードは一気にレベルアップします。

この記事では、
map と flatMap の違い → 基本 → 実践例 → ベストプラクティス
の順番で、完全に理解できるように解説していきます。

Java プログラマーを目指す人や、転職を考えている人にとって、flatMap は避けて通れないポイントです。ぜひ最後まで読んでください。


map と flatMap の違いを直感的に理解しよう

まずはこの二つの違いをシンプルに説明します。

● map は「変換」

ひとつの値を、別の値に変換します。

例:
A → a
B → b
C → c

● flatMap は「変換 + 平らに伸ばす」

ひとつの値から、複数の値が出てくるときに使います。

例:
A → a a a
B → b b
C → c

ただし、そのままだと入れ子構造(List の中に List)ができてしまうので、
flat(平ら)に伸ばしてひとつの Stream にする
というのが flatMap の役割です。

とても大事なポイントなので覚えてください:

map は 値 → 値
flatMap は 値 → 複数の値(そして平坦化)


flatMap の基本的な使い方

では、コードを使って理解していきましょう。

◆ 例:List の中に List があるケース

List<List<String>> fruits = List.of(
    List.of("Apple", "Apricot"),
    List.of("Banana"),
    List.of("Cherry", "Cranberry")
);

List<String> result = fruits.stream()
        .flatMap(list -> list.stream())
        .toList();

System.out.println(result);
// [Apple, Apricot, Banana, Cherry, Cranberry]

もし map を使うと、こうなります。

fruits.stream()
      .map(list -> list.stream())
      .toList();

// Stream<Stream<String>> になってしまう

map ではネストが残り、扱いにくい構造になります。
そこで flatMap を使うと「平ら」にできます。


実践例1:文章を単語に分解

プログラムで文章を単語に分けたいとします。

List<String> sentences = List.of(
    "Java is fun",
    "Stream API is powerful"
);

List<String> words = sentences.stream()
    .flatMap(sentence -> Arrays.stream(sentence.split(" ")))
    .toList();

System.out.println(words);
// [Java, is, fun, Stream, API, is, powerful]

ここでも、
「文章」→「単語の配列」
という変換が起きるため、flatMap が必要になります。


実践例2:社員 → スキルの平坦化

現場の開発では、次のような構造がよくあります。

  • 社員

このようなデータを SQL の JOIN なしで処理したい場合、flatMap が役に立ちます。

◆ モデルクラス

class Employee {
    String name;
    List<String> skills;

    Employee(String name, List<String> skills) {
        this.name = name;
        this.skills = skills;
    }

    List<String> getSkills() {
        return skills;
    }
}

◆ flatMap を使って全スキル一覧を取得

List<Employee> employees = List.of(
    new Employee("Alice", List.of("Java", "Spring")),
    new Employee("Bob", List.of("JavaScript")),
    new Employee("Charlie", List.of("Java", "Docker"))
);

List<String> allSkills = employees.stream()
        .flatMap(e -> e.getSkills().stream())
        .distinct()
        .toList();

System.out.println(allSkills);
// [Java, Spring, JavaScript, Docker]

flatMap によって
社員 → 保有スキル
がひとつの Stream になり、扱いやすい形になります。


flatMap の派生メソッド

flatMap には次のような派生があります。

  • flatMapToInt
  • flatMapToDouble
  • flatMapToLong

プリミティブのストリームに変換したいときに使用します。

例:

flatMapToInt(user -> user.getScores().stream().mapToInt(Integer::intValue))

プリミティブ型のストリームは高速なので、処理が多い場合はこちらが有効です。


flatMap を使うときの注意点

flatMap はとても強力なメソッドですが、使い方を間違えるとコードが読みにくくなります。

● 注意1:複雑な処理を flatMap 内で書かない

ラムダ式の中に複雑なコードを書くと、可読性が落ちます。

● 注意2:null に注意

flatMap 内で null を返すのは厳禁です。
必ず emptyStream() を返すようにしましょう。

return Stream.empty();

● 注意3:型が複雑になりすぎるとエラーが増える

flatMap の戻り値は
Stream<何か>
でなければならないため、型が正しいか常に意識してください。


まとめ:flatMap を使いこなせばプログラマーとして一段レベルアップする

flatMap を理解すれば、以下がスムーズに書けるようになります。

  • ネストしたリストの処理
  • 文章 → 単語の展開
  • オブジェクトのネスト構造の展開
  • SQL に頼らないデータ変換

Java プログラマーとして大きな武器になるメソッドです。


📚 学習の次のステップ

flatMap や Stream API をさらに深く理解するために、まずは
👉 絶対にJavaプログラマーになりたい人へ。
を読んでみてください。

自己学習に最適で、コードの考え方を理解する助けになります。

そして、

  • 読んでも理解できない部分がある
  • ソースコードレビューをしてほしい
  • Java プログラマーとして転職したい
  • 転職サポートまで受けたい

という方は、
👉 サイゼントアカデミー
がおすすめです。

現役エンジニアが、学習と転職を徹底サポートします。

コメント

タイトルとURLをコピーしました