Java Gold SE11対策:flatMapの落とし穴:ネスト解消の正しい知識

JavaのStream APIには、map とよく似た flatMap というメソッドがありますが、この2つを正しく使い分けるのはJava Gold SE11の試験でも重要なポイントです。
特に Optional や List<List<T>> のように、ネストされた構造を扱う場面で「flatMapを使うべきかどうか」を判断できる力が問われます。
この記事では、flatMapの動作原理・使用目的・典型例・試験での引っかけポイントまで、徹底的に解説していきます。
目次
1. mapとflatMapの違いとは?
まず基本の比較から整理しましょう。
メソッド | 入力 | 出力 | 用途 |
map | T → R | Stream<R> | 要素の変換 |
flatMap | T → Stream<R> | Stream<R> | ネストされた構造を平坦化 |
例を見てみます:
List<String> words = List.of(“Java”, “Gold”);
List<Stream<Character>> mapped = words.stream()
.map(word -> word.chars().mapToObj(c -> (char) c))
.collect(Collectors.toList()); // List<Stream<Character>>
このように、map を使うと Stream<Stream<Character>> になります。
一方、flatMap を使うと:
List<Character> flatMapped = words.stream()
.flatMap(word -> word.chars().mapToObj(c -> (char) c))
.collect(Collectors.toList()); // List<Character>
👉 flatMap によって、ネストが「1段階だけ」削除されます。
2. ネストとは?なぜflatMapで解消するの?
Javaでは次のようなネスト構造がよく出てきます:
- List<List<String>>
- Stream<Stream<T>>
- Optional<Optional<T>>
このような構造のままだと扱いづらいため、「中身だけを取り出してひとつにまとめる」処理が必要になります。
それをやってくれるのが flatMap です。
3. List<List<String>> を使った典型例
List<List<String>> nested = List.of(
List.of(“A”, “B”),
List.of(“C”, “D”)
);
// mapでは List<Stream<String>> になってしまう
List<Stream<String>> mapped = nested.stream()
.map(list -> list.stream())
.collect(Collectors.toList());
// flatMapでネストを解消
List<String> flatMapped = nested.stream()
.flatMap(list -> list.stream())
.collect(Collectors.toList());
System.out.println(flatMapped); // [A, B, C, D]
4. Optionalとの連携(Java Goldでも頻出!)
Optional<Optional<T>> もよくあるネスト構造です。
たとえば:
Optional<String> name = Optional.of(“Java”);
Optional<Optional<Integer>> mapped = name.map(s -> Optional.of(s.length()));
Optional<Integer> flatMapped = name.flatMap(s -> Optional.of(s.length()));
👉 map を使うと Optional<Optional<Integer>> になるが、
👉 flatMap を使えば Optional<Integer> になる。
5. flatMapのポイントまとめ
flatMapが必要な場面 |
Stream<Stream<T>> を扱うとき |
List<List<T>> を flatten したいとき |
Optional<Optional<T>> を解消したいとき |
6. 試験で出やすいひっかけパターン
❌ mapで処理 → ネストされた構造が残る
List<Stream<String>> result = names.stream()
.map(name -> Stream.of(name.split(“”)))
.collect(Collectors.toList()); // NG: ネストされたまま
✅ flatMapで処理 → 中身を平坦化
List<String> result = names.stream()
.flatMap(name -> Stream.of(name.split(“”)))
.collect(Collectors.toList()); // OK: 平坦化される
まとめチェックリスト
- map は構造を維持、flatMap はネストを解消する
- Optional<Optional<T>> や Stream<Stream<T>> は flatMap で1段階のネストを削除できる
- ネストがないのに flatMap を使うと意味が変わってしまう → 要注意
- 試験では map().map() か flatMap() のどちらが正しいかを選ばせる問題が出る
おわりに
flatMap は一見すると難しく感じるかもしれませんが、「ネストを1段階だけ削除する」というシンプルな役割を正しく理解していれば、迷うことはありません。
Java Gold SE11の試験では、OptionalやListのネストをどう扱うかが問われるため、flatMap の理解は合格に直結します。