はじめに:なぜ 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 があるケース
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
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 を使うと、こうなります。
|
1 2 3 4 5 6 |
fruits.stream() .map(list -> list.stream()) .toList(); // Stream<Stream<String>> になってしまう |
map ではネストが残り、扱いにくい構造になります。
そこで flatMap を使うと「平ら」にできます。
実践例1:文章を単語に分解
プログラムで文章を単語に分けたいとします。
|
1 2 3 4 5 6 7 8 9 10 11 12 |
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 が役に立ちます。
◆ モデルクラス
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
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 を使って全スキル一覧を取得
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
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
プリミティブのストリームに変換したいときに使用します。
例:
|
1 2 |
flatMapToInt(user -> user.getScores().stream().mapToInt(Integer::intValue)) |
プリミティブ型のストリームは高速なので、処理が多い場合はこちらが有効です。
flatMap を使うときの注意点
flatMap はとても強力なメソッドですが、使い方を間違えるとコードが読みにくくなります。
● 注意1:複雑な処理を flatMap 内で書かない
ラムダ式の中に複雑なコードを書くと、可読性が落ちます。
● 注意2:null に注意
flatMap 内で null を返すのは厳禁です。
必ず emptyStream() を返すようにしましょう。
|
1 2 |
return Stream.empty(); |
● 注意3:型が複雑になりすぎるとエラーが増える
flatMap の戻り値は
Stream<何か>
でなければならないため、型が正しいか常に意識してください。
まとめ:flatMap を使いこなせばプログラマーとして一段レベルアップする
flatMap を理解すれば、以下がスムーズに書けるようになります。
- ネストしたリストの処理
- 文章 → 単語の展開
- オブジェクトのネスト構造の展開
- SQL に頼らないデータ変換
Java プログラマーとして大きな武器になるメソッドです。
📚 学習の次のステップ
flatMap や Stream API をさらに深く理解するために、まずは
👉 「絶対にJavaプログラマーになりたい人へ。」
を読んでみてください。
自己学習に最適で、コードの考え方を理解する助けになります。
そして、
- 読んでも理解できない部分がある
- ソースコードレビューをしてほしい
- Java プログラマーとして転職したい
- 転職サポートまで受けたい
という方は、
👉 サイゼントアカデミー
がおすすめです。
現役エンジニアが、学習と転職を徹底サポートします。


コメント