Post

Java Stream API

map() vs flatMap()

Java Stream API

๐Ÿ“Œ๊ฐœ์š”

Java Stream API๋Š” Java 8์—์„œ ๋„์ž…๋œ ๊ฐ•๋ ฅํ•œ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๋„๊ตฌ๋กœ,ย map()๊ณผย flatMap()์€ ์ŠคํŠธ๋ฆผ ์š”์†Œ๋ฅผ ๋ณ€ํ™˜ํ•˜๋Š” ํ•ต์‹ฌ ์—ฐ์‚ฐ์ž์ด๋‹ค.

๋‘ ๋ฉ”์„œ๋“œ์˜ ์ฐจ์ด์ ์„ ๋ช…ํ™•ํžˆ ๊ตฌ๋ถ„ํ•˜๊ณ , ์‹ค์ œ ์ฝ”๋“œ ์˜ˆ์ œ๋ฅผ ํ†ตํ•ด ํ™œ์šฉ ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•œ๋‹ค. ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํŒจ๋Ÿฌ๋‹ค์ž„์„ ์ดํ•ดํ•˜๊ณ  ๋ณต์žกํ•œ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ํ•™์Šตํ•  ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ“Œ๋‚ด์šฉ

ํ•ต์‹ฌ ๊ฐœ๋… ๋น„๊ต

ํŠน์„ฑmap()flatMap()
๋ณ€ํ™˜ ๋ฐฉ์‹1:1 ๋ณ€ํ™˜1:N ๋ณ€ํ™˜ + ํ‰ํƒ„ํ™”
์ž…/์ถœ๋ ฅ ๊ด€๊ณ„A โ†’ BA โ†’ [B1, B2, B3] โ†’ B1, B2, B3
๋ฐ˜ํ™˜ ํƒ€์ž…Stream<R>Stream<R> (๋‚ด๋ถ€ ์ŠคํŠธ๋ฆผ ํ’€์–ด๋ƒ„)
์ฃผ์š” ์‚ฌ์šฉ ์ผ€์ด์Šค๋‹จ์ˆœ ๊ฐ’ ๋ณ€ํ™˜์ค‘์ฒฉ ์ปฌ๋ ‰์…˜ ์ฒ˜๋ฆฌ, ๋‹ค์ค‘ ๊ฐ’ ์ƒ์„ฑ
์˜ˆ์‹œ๋ฌธ์ž์—ด ๊ธธ์ด ์ถ”์ถœ๋ฌธ์žฅ์„ ๋‹จ์–ด๋กœ ๋ถ„ํ•ด

๋™์ž‘ ๋ฐฉ์‹

Java-StreamAPI-map-and-flatMap

map()

map()์€ ๊ฐ ์›์†Œ๋ฅผ 1:1๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ์›๋ณธ ๋ฐฐ์—ด๊ณผ ๋™์ผํ•œ ๊ธธ์ด์˜ ์ƒˆ ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

  • ๋‹จ์ผ ์†์„ฑ ์ถ”์ถœ, ๋‹จ์ˆœ ํƒ€์ž… ๋ณ€ํ™˜ ๋“ฑ ๋‹จ์ˆœ ๊ณ„์‚ฐ
  • 1:1 ๋งคํ•‘์ด ๋ณด์žฅ๋œ ๊ฒฝ์šฐ
1
2
3
4
// ๋Œ€์†Œ๋ฌธ์ž ๋ณ€ํ™˜
List<String> names = Arrays.asList("java", "stream");
List<String> upperNames = names.stream().map(String::toUpperCase).collect(Collectors.toList());
// ๊ฒฐ๊ณผ: ["JAVA", "STREAM"]

flatMap()

flatMap()์€ 1:N ๋ถ„ํ•ด ํ›„ ํ‰ํƒ„ํ™”๋กœ ๊ธธ์ด๋ฅผ ๊ฐ€๋ณ€์ ์œผ๋กœ ๋งŒ๋“ ๋‹ค.

  • ์ปฌ๋ ‰์…˜ ํ’€๊ธฐ, ๋ฌธ์ž์—ด ํ† ํฐํ™”, Optional ์ฒด์ด๋‹ ๋“ฑ
  • ํ•˜๋‚˜์˜ ์ž…๋ ฅ์ด ์—ฌ๋Ÿฌ ์ถœ๋ ฅ์„ ์ƒ์„ฑํ•ด์•ผ ํ•  ๋•Œ
1
2
3
4
5
6
7
8
9
10
11
12
// ๋‹ค์ค‘ ๋ฆฌ์ŠคํŠธ ํ‰ํƒ„ํ™”
List<List<Integer>> numberLists = Arrays.asList(
    Arrays.asList(1, 2),
    Arrays.asList(3, 4, 5)
);
List<Integer> allNumbers = numberLists.stream().flatMap(List::stream).collect(Collectors.toList());
// ๊ฒฐ๊ณผ: [1, 2, 3, 4, 5]

// ๋ฌธ์ž์—ด ํ† ํฐํ™”
List<String> sentences = Arrays.asList("Hello World", "Java Stream");
List<String> words = sentences.stream().flatMap(s -> Arrays.stream(s.split(" "))).collect(Collectors.toList());
// ๊ฒฐ๊ณผ: ["Hello", "World", "Java", "Stream"]

๋™์ž‘ ๋ฐฉ์‹ ๋น„๊ต

์—ฐ์‚ฐ์ž์ž…/์ถœ๋ ฅ ๊ณผ์ •๊ธธ์ด ๋ณ€ํ™”
map()[A, B] โ†’ [f(A), f(B)]์œ ์ง€ (n โ†’ n)
flatMap()[A, B] โ†’ [A1, A2, ...] + [B1, B2, ...] โ†’ [A1, A2, ..., B1, B2, ...]๊ฐ€๋ณ€ (n โ†’ m)

๐ŸŽฏ๊ฒฐ๋ก 

flatMap()์ด ๋” ๊ฐ•๋ ฅํ•˜์ง€๋งŒ, map()์œผ๋กœ ํ•ด๊ฒฐ ๊ฐ€๋Šฅํ•œ ์ž‘์—…์—๋Š” map()์„ ์‚ฌ์šฉํ•˜์ž. ์ค‘์ฒฉ ๊ตฌ์กฐ ๋ถ„ํ•ด๋‚˜ 1:Nย ๋ณ€ํ™˜์ด ํ•„์š”ํ•  ๋•Œ๋งŒ flatMap()์„ ์„ ํƒํ•˜๋Š” ๊ฒƒ์ด ์„ฑ๋Šฅ๊ณผ ๊ฐ€๋…์„ฑ ๋ฉด์—์„œ ์œ ๋ฆฌํ•  ๊ฒƒ์ด๋‹ค.

map()

  • ๋‹จ์ผ ์†์„ฑ ์ถ”์ถœ, ๋‹จ์ˆœ ํƒ€์ž… ๋ณ€ํ™˜ ๋“ฑ ๋‹จ์ˆœ ๊ณ„์‚ฐ
  • 1:1 ๋งคํ•‘์ด ๋ณด์žฅ๋œ ๊ฒฝ์šฐ
  • ์„ฑ๋Šฅ์ด ๋” ์ค‘์š”ํ•œ ๊ฒฝ์šฐ

flatMap()

  • ์ปฌ๋ ‰์…˜ ํ’€๊ธฐ, ๋ฌธ์ž์—ด ํ† ํฐํ™”, Optional ์ฒด์ด๋‹ ๋“ฑ
  • ํ•˜๋‚˜์˜ ์ž…๋ ฅ์ด ์—ฌ๋Ÿฌ ์ถœ๋ ฅ์„ ์ƒ์„ฑํ•ด์•ผ ํ•  ๋•Œ
  • ๋‚ด๋ถ€ ์ŠคํŠธ๋ฆผ ์ƒ์„ฑ ์˜ค๋ฒ„ํ—ค๋“œ ์กด์žฌ

๊ฐ€๋…์„ฑ vs ๊ธฐ๋Šฅ

  • ๋‹จ์ˆœ ๋ณ€ํ™˜์€ map()์ด ๋” ์ง๊ด€์ 
  • ๋ณต์žกํ•œ ๋ถ„ํ•ด ๋กœ์ง์€ flatMap()์ด ์œ ๋ฆฌ
  • ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์‹œ map().flatMap() ๋ถ„๋ฆฌ ๊ณ ๋ ค

โš™๏ธEndNote

ํ•„์š”ํ•œ ์‚ฌ์ „ ์ง€์‹

  1. ๋žŒ๋‹ค ํ‘œํ˜„์‹: (x) -> x*2 ๊ฐ™์€ ๊ฐ„๊ฒฐํ•œ ํ•จ์ˆ˜ ์ •์˜ ๋ฐฉ์‹
  2. ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค: Function<T, R>, Predicate<T> ๋“ฑ

๋” ์•Œ์•„๋ณด๊ธฐ

์„ฑ๋Šฅ ๊ณ ๋ ค์‚ฌํ•ญ

  • flatMap()์€ ์ค‘๊ฐ„ ์ŠคํŠธ๋ฆผ ์ƒ์„ฑ ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค.
  • ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ(parallelStream())์—์„œ์˜ ๋™์ž‘ ์ฐจ์ด

Optional์˜ flatMap()

  • Optional ํด๋ž˜์Šค์—์„œ๋„ ๋™์ผํ•œ ๊ฐœ๋… ์ ์šฉ ๊ฐ€๋Šฅ
1
Optional.of("hello").flatMap(s -> Optional.of(s.length()));

Reactivestreams์™€์˜ ์—ฐ๊ด€์„ฑ

  • RxJava/Project Reactor์—์„œ๋„ ์œ ์‚ฌํ•œ ์—ฐ์‚ฐ์ž ์‚ฌ์šฉ
This post is licensed under CC BY 4.0 by the author.