0Pricing
Java Academy · レッスン

ネストしたコレクションに対するflatMap

flatMapを使って、ネストしたリスト、Optionalのチェーン、ファイルの行構造を平坦化します。

「ネストしたコレクションに対するflatMap」はCoddyKit上の無料Java Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはJava Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Java Academyコースには全4レッスンが含まれています。

ネストしたコレクションの問題

ストリームの各要素を別のコレクションにマッピングすると、map の結果は Stream<List<T>> になります。flatMap は内部のストリームを1つのフラットな Stream<T> に結合します。

List<List<Integer>> nested = List.of(List.of(1,2), List.of(3,4), List.of(5));
// With map:
Stream<List<Integer>> s = nested.stream().map(l -> l); // Stream<List<Integer>>
// With flatMap:
Stream<Integer> flat = nested.stream().flatMap(List::stream); // Stream<Integer>
flat.forEach(System.out::println); // 1 2 3 4 5

flatMapとmapの違い

map(f) は各要素に f を適用し、結果をラップします。flatMap(f) はストリームを返す f を適用し、それらすべてのストリームを1つに連結します。

// map: List<String> -> Stream<Stream<Character>>
Stream<Stream<Character>> nested = List.of("hi","bye").stream()
    .map(s -> s.chars().mapToObj(c -> (char)c));
// flatMap: List<String> -> Stream<Character>
Stream<Character> flat = List.of("hi","bye").stream()
    .flatMap(s -> s.chars().mapToObj(c -> (char)c));

注文と商品をフラット化する

典型的な用途は、各注文が商品のリストを持つ場合です。すべての注文に含まれる商品を、1つのフラットなストリームとして取得できます。

List<String> allItems = orders.stream()
    .flatMap(order -> order.getItems().stream())
    .collect(Collectors.toList());
System.out.println(allItems);

OptionalとflatMap

Optional に対して stream()(Java 9以降)を使用すると、0個または1個の要素を持つストリームに変換できます。その後、flatMap によって Stream<Optional<T>> を Stream<T> に平坦化できます。

List<Optional<String>> maybes = List.of(Optional.of("a"), Optional.empty(), Optional.of("c"));
List<String> values = maybes.stream()
    .flatMap(Optional::stream)  // Java 9+
    .collect(Collectors.toList());
System.out.println(values); // [a, c]

複数ファイルから全行を読み取る

flatMap を使うと、入れ子のループを使わずに、ファイルのリストに含まれるすべての行を1つのストリームへ簡単に連結できます。

List<Path> files = List.of(Path.of("a.txt"), Path.of("b.txt"));
List<String> allLines = files.stream()
    .flatMap(p -> {
        try { return Files.lines(p); }
        catch (IOException e) { return Stream.empty(); }
    })
    .collect(Collectors.toList());

文字列を単語に分割する

各文を単語に分割し、すべての単語を1つのストリームに平坦化して、単語の出現頻度を数えます。

List<String> sentences = List.of("hello world", "java streams rock");
Map<String, Long> freq = sentences.stream()
    .flatMap(s -> Arrays.stream(s.split("\\s+")))
    .collect(Collectors.groupingBy(w -> w, Collectors.counting()));
System.out.println(freq);

Map.entrySetでflatMapを使う

カテゴリから商品のリストへのマップを平坦化し、すべての商品のストリームに変換します。

Map<String, List<String>> catalog = Map.of(
    "fruit", List.of("apple","banana"),
    "veg",   List.of("carrot","pea"));
List<String> all = catalog.values().stream()
    .flatMap(List::stream)
    .sorted()
    .collect(Collectors.toList());
System.out.println(all); // [apple, banana, carrot, pea]

flatMapでNullPointerExceptionを回避する

関数がストリームの代わりに null を返す可能性がある場合は、null チェックを行うか、Stream.empty() を返して NullPointerException を回避してください。

departments.stream()
    .flatMap(dept -> dept.getEmployees() == null
        ? Stream.empty()
        : dept.getEmployees().stream())
    .forEach(System.out::println);

flatMapで重複しない単語を数える

flatMap、distinct、count を組み合わせると、データ処理を簡潔に記述できます。

long distinctWords = sentences.stream()
    .flatMap(s -> Arrays.stream(s.toLowerCase().split("[^a-z]+")))
    .filter(w -> !w.isEmpty())
    .distinct()
    .count();
System.out.println("Distinct: " + distinctWords);

プリミティブストリーム用のflatMapToInt

プリミティブストリームに平坦化するときは、flatMapToInt、flatMapToLong、flatMapToDouble を使用してボクシングを回避します。

int totalQuantity = orders.stream()
    .flatMapToInt(order -> order.getItems().stream().mapToInt(Item::getQuantity))
    .sum();
System.out.println("Total qty: " + totalQuantity);

パフォーマンスに関する注意

各 flatMap 呼び出しはストリームの層を1つ追加します。小さな内部コレクションが多数ある非常に大規模なデータセットでは、オブジェクト生成のオーバーヘッドを減らすために、反復的なアプローチや Spliterator の使用を検討してください。

確認問題

flatMap は map と異なり、何を行いますか?

まとめ

flatMap は各要素をストリームに変換し、すべてのストリームを1つに結合します。ネストしたコレクションの平坦化、Optional の連結、文字列の分割、複数ファイルの読み取りに使用します。ボクシングを回避するには flatMapToInt を使用します。

よくある質問

「ネストしたコレクションに対するflatMap」レッスンは無料ですか?

はい。「ネストしたコレクションに対するflatMap」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Java Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Java Academyコースには全4レッスンが含まれています。

「ネストしたコレクションに対するflatMap」で何を学びますか?

flatMapを使って、ネストしたリスト、Optionalのチェーン、ファイルの行構造を平坦化します。 ブラウザで直接実行するハンズオンコードでJava Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Java Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのJava Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。

「ネストしたコレクションに対するflatMap」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このJava Academyレッスンでコードを書いて実行できますか?

はい。すべてのJava Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. ネストしたコレクションに対するflatMap
  2. 並列ストリーム:性能と注意点
  3. Spliterator:並列処理のための分割
  4. iterateとgenerateによる無限ストリーム
← Java Academyに戻る