0Pricing
Java Academy · 강의

toMap, joining, summarizing

스트림을 맵으로 변환하고 joining으로 문자열을 연결하며 summarizingInt로 통계를 계산합니다.

toMap, joining, summarizing은(는) CoddyKit의 무료 Java Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Java Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Java Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

Collectors.toMap 기본

Collectors.toMap(keyMapper, valueMapper)는 stream을 맵으로 변환합니다. 각 요소가 하나의 키-값 쌍을 제공합니다.

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을 발생시킵니다. 충돌을 해결하려면 세 번째 인수로 병합 함수를 제공합니다:

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()을 사용합니다. 이는 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()는 한 번의 순회로 모든 통계를 계산하고 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

하나의 통계만 필요한 더 단순한 경우에는 다음을 사용합니다:

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 행을 분석하여 맵으로 변환합니다:

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

빠른 확인

같은 키를 가진 두 요소가 포함된 stream에서 Collectors.toMap(k, v)를 사용하면 어떻게 됩니까?

복습: toMap, joining, summarizing

핵심 내용:

  • toMap(keyMapper, valueMapper) — 병합 함수가 없으면 중복 키에서 예외를 발생시킵니다
  • joining(구분자, 접두사, 접미사) — 문자열을 간결하게 연결합니다
  • summarizingInt는 한 번의 순회로 개수+합계+최솟값+최댓값+평균을 제공합니다
  • 하나의 통계만 필요할 때는 summingInt/averagingInt를 사용합니다
  • 순서가 있는 결과를 얻으려면 LinkedHashMap::new와 함께 4개 인수 toMap을 사용합니다

자주 묻는 질문

“toMap, joining, summarizing” 강의는 무료인가요?

네 — “toMap, joining, summarizing” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Java Academy 강의 전체를 잠금 해제할 수 있습니다. Java Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“toMap, joining, summarizing”에서 뭘 배우나요?

스트림을 맵으로 변환하고 joining으로 문자열을 연결하며 summarizingInt로 통계를 계산합니다. 브라우저에서 직접 실행하는 실습 코드로 Java Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Java Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Java Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.

“toMap, joining, summarizing” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Java Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Java Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. groupingBy: 요소 분류
  2. partitioningBy와 counting
  3. toMap, joining, summarizing
  4. 사용자 정의 수집기 만들기
← Java Academy(으)로 돌아가기