Java Stream API
map() vs flatMap()
๐๊ฐ์
Java Stream API๋ Java 8์์ ๋์
๋ ๊ฐ๋ ฅํ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ๋๊ตฌ๋ก,ย map()
๊ณผย flatMap()
์ ์คํธ๋ฆผ ์์๋ฅผ ๋ณํํ๋ ํต์ฌ ์ฐ์ฐ์์ด๋ค.
๋ ๋ฉ์๋์ ์ฐจ์ด์ ์ ๋ช ํํ ๊ตฌ๋ถํ๊ณ , ์ค์ ์ฝ๋ ์์ ๋ฅผ ํตํด ํ์ฉ ๋ฐฉ๋ฒ์ ์ค๋ช ํ๋ค. ํจ์ํ ํ๋ก๊ทธ๋๋ฐ ํจ๋ฌ๋ค์์ ์ดํดํ๊ณ ๋ณต์กํ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ํจ์จ์ ์ผ๋ก ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ํ์ตํ ์ ์๋ค.
๐๋ด์ฉ
ํต์ฌ ๊ฐ๋ ๋น๊ต
ํน์ฑ | map() | flatMap() |
---|---|---|
๋ณํ ๋ฐฉ์ | 1:1 ๋ณํ | 1:N ๋ณํ + ํํํ |
์ /์ถ๋ ฅ ๊ด๊ณ | A โ B | A โ [B1, B2, B3] โ B1, B2, B3 |
๋ฐํ ํ์ | Stream<R> | Stream<R> (๋ด๋ถ ์คํธ๋ฆผ ํ์ด๋) |
์ฃผ์ ์ฌ์ฉ ์ผ์ด์ค | ๋จ์ ๊ฐ ๋ณํ | ์ค์ฒฉ ์ปฌ๋ ์ ์ฒ๋ฆฌ, ๋ค์ค ๊ฐ ์์ฑ |
์์ | ๋ฌธ์์ด ๊ธธ์ด ์ถ์ถ | ๋ฌธ์ฅ์ ๋จ์ด๋ก ๋ถํด |
๋์ ๋ฐฉ์
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
ํ์ํ ์ฌ์ ์ง์
- ๋๋ค ํํ์:
(x) -> x*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์์๋ ์ ์ฌํ ์ฐ์ฐ์ ์ฌ์ฉ