0Pricing
Java Academy · レッスン

toMap、joining、summarizing

ストリームをマップに変換し、joining で文字列を連結し、summarizingInt で統計値を計算します。

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

Collectors.toMapの基本

Collectors.toMap(keyMapper, valueMapper)は、ストリームをMapに変換します。各要素から1つのキーと値の組が生成されます。

import java.util.*;
import java.util.stream.*;

record Country(String code, String name) {}
List<Country> countries = List.of(
    new Country("US","United States"),
    new Country("DE","Germany"),
    new Country("JP","Japan")
);

Map<String, String> codeToName =
    countries.stream().collect(
        Collectors.toMap(Country::code, Country::name)
    );
System.out.println(codeToName.get("DE")); // Germany

重複キーの処理

toMapは、キーが重複するとIllegalStateExceptionをスローします。3番目の引数としてマージ関数を渡すと、競合を解決できます:

List<String> words = List.of("apple","ant","banana","bat","cherry");

Map<Character, String> firstByLetter =
    words.stream().collect(
        Collectors.toMap(
            w -> w.charAt(0),
            w -> w,
            (existing, replacement) -> existing // keep first
        )
    );
System.out.println(firstByLetter); // {a=apple, b=banana, c=cherry}

値の変換を伴うtoMap

値マッパーには任意の関数を指定できます。格納する前に要素を変換します:

record User(String login, String email) {}
List<User> users = List.of(
    new User("alice","alice@example.com"),
    new User("bob","bob@example.com")
);

Map<String, String> loginToEmail =
    users.stream().collect(
        Collectors.toMap(User::login, u -> u.email().toUpperCase())
    );
System.out.println(loginToEmail.get("alice")); // ALICE@EXAMPLE.COM

toUnmodifiableMap

Collectors.toUnmodifiableMap()を使用すると、不変Mapを生成できます。これはCollections.unmodifiableMap()でラップするのと同等ですが、より簡潔です:

Map<String, Integer> wordLengths =
    Stream.of("Java","Stream","API")
          .collect(Collectors.toUnmodifiableMap(w -> w, String::length));
// wordLengths.put("test",4); // throws UnsupportedOperationException

Collectors.joining

Collectors.joining()は、文字列要素を連結します。区切り文字、接頭辞、接尾辞をオプションで指定できます:

List<String> names = List.of("Alice","Bob","Carol");

System.out.println(names.stream().collect(Collectors.joining()));
// AliceBobCarol

System.out.println(names.stream().collect(Collectors.joining(", ")));
// Alice, Bob, Carol

System.out.println(names.stream().collect(Collectors.joining(", ", "[", "]")));
// [Alice, Bob, Carol]

CSV出力のためのjoining

joiningを使用して、CSVの行やSQLのIN句を作成できます:

List<Integer> ids = List.of(1,2,3,4,5);

String inClause = ids.stream()
    .map(Object::toString)
    .collect(Collectors.joining(",", "(", ")"));
System.out.println("WHERE id IN " + inClause);
// WHERE id IN (1,2,3,4,5)

summarizingInt / Long / Double

Collectors.summarizingInt()は、1回の走査ですべての統計値を計算し、IntSummaryStatisticsを返します:

record Product(String name, int price) {}
List<Product> products = List.of(
    new Product("A",100), new Product("B",200), new Product("C",150)
);

IntSummaryStatistics stats =
    products.stream().collect(Collectors.summarizingInt(Product::price));

System.out.println("Count: " + stats.getCount());   // 3
System.out.println("Sum: "   + stats.getSum());     // 450
System.out.println("Min: "   + stats.getMin());     // 100
System.out.println("Max: "   + stats.getMax());     // 200
System.out.println("Avg: "   + stats.getAverage()); // 150.0

summingIntとaveragingInt

必要な統計値が1つだけの場合は、より単純な方法を使用できます:

int total = products.stream().collect(Collectors.summingInt(Product::price));
System.out.println("Total: " + total); // 450

double avg = products.stream().collect(Collectors.averagingInt(Product::price));
System.out.println("Average: " + avg); // 150.0

summarizingIntを使用したgroupingBy

グループごとの集計を組み合わせます:

record Sale(String region, int amount) {}
List<Sale> sales = List.of(
    new Sale("North",100), new Sale("South",200),
    new Sale("North",150), new Sale("South",300)
);

Map<String, IntSummaryStatistics> statsByRegion =
    sales.stream().collect(
        Collectors.groupingBy(Sale::region,
            Collectors.summarizingInt(Sale::amount))
    );
statsByRegion.forEach((r,s) ->
    System.out.printf("%s: sum=%d avg=%.1f%n", r, s.getSum(), s.getAverage()));

LinkedHashMapへの収集

toMapはデフォルトでHashMap(順序なし)を生成します。4引数版のオーバーロードを使用すると、挿入順を保持するLinkedHashMapを指定できます:

Map<String, Integer> ordered =
    Stream.of("banana","apple","cherry")
          .collect(Collectors.toMap(
              w -> w,
              String::length,
              (a,b) -> a,
              LinkedHashMap::new
          ));
System.out.println(ordered.keySet()); // [banana, apple, cherry]

実践例: 設定パーサー

toMapを使用して、key=value形式の行をMapに解析します:

List<String> lines = List.of("host=localhost","port=5432","db=myapp");

Map<String, String> config =
    lines.stream()
         .map(l -> l.split("=", 2))
         .collect(Collectors.toMap(a -> a[0], a -> a[1]));

System.out.println(config.get("port")); // 5432

理解度チェック

同じキーを持つ2つの要素を含むストリームに対して、Collectors.toMap(k, v)を使用します。何が起こりますか?

復習: toMap、joining、summarizing

重要なポイント:

  • toMap(keyMapper, valueMapper) — マージ関数がない場合、重複キーで例外をスローします
  • joining(delimiter, prefix, suffix) — 文字列を効率よく連結します
  • summarizingIntは、1回の走査で件数+合計+最小値+最大値+平均値を計算します
  • 1つの統計値だけが必要な場合はsummingInt/averagingIntを使用します
  • 順序付きの結果には、LinkedHashMap::newを指定した4引数版toMapを使用します

よくある質問

「toMap、joining、summarizing」レッスンは無料ですか?

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

「toMap、joining、summarizing」で何を学びますか?

ストリームをマップに変換し、joining で文字列を連結し、summarizingInt で統計値を計算します。 ブラウザで直接実行するハンズオンコードでJava Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

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

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

「toMap、joining、summarizing」レッスンにはどのくらい時間がかかりますか?

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

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

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

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

  1. groupingBy:要素の分類
  2. partitioningBy と counting
  3. toMap、joining、summarizing
  4. カスタム Collector の作成
← Java Academyに戻る