๊ด€๋ฆฌ ๋ฉ”๋‰ด

Unfazedโ—๏ธ๐ŸŽฏ

Java Stream API - map() & flatMap() ๋ณธ๋ฌธ

Java

Java Stream API - map() & flatMap()

9taetae9 2025. 1. 20. 09:04
728x90

Java 8์—์„œ ๋„์ž…๋œ Stream API๋Š” ์ปฌ๋ ‰์…˜์„ ์ฒ˜๋ฆฌํ•˜๋Š” ํšจ๊ณผ์ ์ธ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•œ๋‹ค. ๊ทธ ์ค‘์—์„œ๋„ map()๊ณผ flatMap() ๋ฉ”์„œ๋“œ๋Š” ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜๊ณผ ์ฒ˜๋ฆฌ์— ์žˆ์–ด ํ•ต์‹ฌ์ ์ธ ์—ญํ• ์„ ํ•œ๋‹ค.

 

1. map()

<R> Stream<R> map(
        Function<? super T, // T : ์ž…๋ ฅ ํƒ€์ž… (์›๋ณธ ์ŠคํŠธ๋ฆผ์˜ ์š”์†Œ ํƒ€์ž…)
        ? extends R> mapper // R : ์ถœ๋ ฅ ํƒ€์ž… (์ƒˆ๋กœ์šด ์ŠคํŠธ๋ฆผ์˜ ์š”์†Œ ํƒ€์ž…)
)

map() ๋ฉ”์„œ๋“œ๋Š” ์ŠคํŠธ๋ฆผ์˜ ๊ฐ ์š”์†Œ๋ฅผ ๋‹ค๋ฅธ ์š”์†Œ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” 1:1 ๋งคํ•‘์„ ์ˆ˜ํ–‰ํ•œ๋‹ค. ์ž…๋ ฅ ์š”์†Œ ํ•˜๋‚˜๋‹น ์ •ํ™•ํžˆ ํ•˜๋‚˜์˜ ์ถœ๋ ฅ ์š”์†Œ๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค.

์ฃผ์š” ํŠน์ง•

  • ๊ฐ ์š”์†Œ๋ฅผ ๋…๋ฆฝ์ ์œผ๋กœ ๋ณ€ํ™˜
  • ์ŠคํŠธ๋ฆผ์˜ ์š”์†Œ ๊ฐœ์ˆ˜ ์œ ์ง€ (one-to-one)
  • ์›๋ณธ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ ๋ณด์กด
  • ๋ฐ˜ํ™˜ ํƒ€์ž…: Stream<R> (R์€ ๋ณ€ํ™˜๋œ ํƒ€์ž…)

์˜ˆ์‹œ ์ฝ”๋“œ

// ๋ฌธ์ž์—ด ๊ธธ์ด ๋ณ€ํ™˜
List<String> words = Arrays.asList("Java", "Stream", "API");
List<Integer> wordLengths = words.stream()
        .map(String::length)
        .collect(Collectors.toList());
// ๊ฒฐ๊ณผ: [4, 6, 3]
// ๊ฐ์ฒด ๋ณ€ํ™˜
List<User> users = getUserList();
List<String> userNames = users.stream()
        .map(User::getName)
        .collect(Collectors.toList());

2. flatMap() 

 

<R> Stream<R> flatMap(
        Function<? super T,    // T : ์ž…๋ ฅ ํƒ€์ž… (์›๋ณธ ์ŠคํŠธ๋ฆผ์˜ ์š”์†Œ ํƒ€์ž…)
        ? extends Stream<? extends R>> mapper // R : ์ถœ๋ ฅ ํƒ€์ž… (์ƒˆ๋กœ์šด ์ŠคํŠธ๋ฆผ์˜ ์š”์†Œ ํƒ€์ž…)
)

flatMap()์€ ์ค‘์ฒฉ๋œ ์ŠคํŠธ๋ฆผ ๊ตฌ์กฐ๋ฅผ ๋‹จ์ผ ๋ ˆ๋ฒจ๋กœ ํ‰๋ฉดํ™”ํ•˜๋ฉด์„œ ๋ณ€ํ™˜ํ•˜๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ๋‹ค. ๊ฐ ์š”์†Œ๋ฅผ ์ŠคํŠธ๋ฆผ์œผ๋กœ ๋ณ€ํ™˜ํ•œ ํ›„, ํ•˜๋‚˜์˜ ์ŠคํŠธ๋ฆผ์œผ๋กœ ๋ณ‘ํ•ฉํ•œ๋‹ค.

์ฃผ์š” ํŠน์ง•

  • ์ค‘์ฒฉ ๊ตฌ์กฐ๋ฅผ ๋‹จ์ผ ๋ ˆ๋ฒจ๋กœ ํ‰๋ฉดํ™”
  • ์š”์†Œ๋ฅผ 0๊ฐœ ์ด์ƒ์˜ ์š”์†Œ๋กœ ๋ณ€ํ™˜ ๊ฐ€๋Šฅ (one-to-many)
  • ์ปฌ๋ ‰์…˜์˜ ๊ณ„์ธต ๊ตฌ์กฐ ์ œ๊ฑฐ
  • ๋ฐ˜ํ™˜ ํƒ€์ž…: Stream<R> (์ค‘์ฒฉ๋œ ์ŠคํŠธ๋ฆผ์„ ๋‹จ์ผ ์ŠคํŠธ๋ฆผ์œผ๋กœ ๋ณ€ํ™˜)

 

  • ๊ฐ’ ์ƒ์„ฑ ๋ฐฉ๋ฒ•
    • 0๊ฐœ ๊ฐ’ ๋ฐ˜ํ™˜: Stream.empty()
    • ์—ฌ๋Ÿฌ ๊ฐ’ ๋ฐ˜ํ™˜: Stream.of(a, b, c)

 

Stream<List<Integer>> ํƒ€์ž…์˜ numbers.stream()์„ flatMap์„ ์‚ฌ์šฉํ•ด Stream<Integer>๋กœ ๋ณ€ํ™˜ ํ›„ ๋ฆฌ์ŠคํŠธ๋กœ ๋ฐ˜ํ™˜.

flatMap์€ ๊ฐ ์ž…๋ ฅ๊ฐ’์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ๊ฐœ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์œ ์—ฐํ•œ ์ฒ˜๋ฆฌ๋„ ๊ฐ€๋Šฅํ•˜๋‹ค.

class User {
    private String name;
    private List<String> emails;
    // getters, setters...
}

List<String> allEmails = users.stream()
        .flatMap(user -> user.getEmails().stream())
        .collect(Collectors.toList());

์œ„ ์ฝ”๋“œ์—์„œ๋Š” ๋ชจ๋“  email ์ถœ๋ ฅ์„ ์œ„ํ•ด ๊ฐ User๋ณ„ email์ด ๊ฐ์ž์˜ ๋ฆฌ์ŠคํŠธ๋กœ ๊ตฌ๋ณ„๋˜์–ด email์ด ์ถœ๋ ฅ๋˜์ง€ ์•Š๊ณ  ๋ชจ๋“  email์„ ํ•˜๋‚˜์˜ ๋ฆฌ์ŠคํŠธ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด flatMap์„ ์‚ฌ์šฉํ•˜์˜€๋‹ค.

 

3. ์‹ค์ œ ํ™œ์šฉ ์‚ฌ๋ก€

class Order {
    private List<Product> products;
    // getters, setters...
}

class Product {
    private String name;
    private double price;
    // getters, setters...
}

// ๋ชจ๋“  ์ฃผ๋ฌธ์˜ ์ด ๊ธˆ์•ก ๊ณ„์‚ฐ
double totalValue = orders.stream()
        .flatMap(order -> order.getProducts().stream())
        .mapToDouble(Product::getPrice)
        .sum();

// ๋ชจ๋“  ์ œํ’ˆ ์ด๋ฆ„ ์ถ”์ถœ
List<String> productNames = orders.stream()
        .flatMap(order -> order.getProducts().stream())
        .map(Product::getName)
        .distinct()
        .collect(Collectors.toList());

์ด๋ ‡๊ฒŒ ๊ฐ ์ฃผ๋ฌธ์ด๋‚˜ ์ œํ’ˆ ๋ณ„์ด ์•„๋‹Œ ์ „์ฒด์ ์ธ ํ†ต๊ณ„๋‚˜ ํ’ˆ๋ชฉ์„ ์ถ”์ถœํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ flatMap์ด ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ๊ฐ€ ๋œ๋‹ค.

 

 

728x90