Introduce
Java์ Stream์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ๋ค์๊ณผ ๊ฐ์ด Stream Pipeline์์
List
๋ฅผ ๋ง๋๋ ๊ฒฝ์ฐ๊ฐ ์๋ค.ย
public class Main { public static void main(String[] args) { Stream.of("0123456789".split("")) // ["0", "1", ..., "9"] .parallel() // parallel stream .map(Main::genList) // Generate List .forEach(System.out::println); } private static List<String> genList(String contents) { return Arrays.asList( String.valueOf(new char[3]).replaceAll("\0", contents).split("")); } }
// output (parallel) [5, 5, 5] [2, 2, 2] [6, 6, 6] [3, 3, 3] [4, 4, 4] [8, 8, 8] [9, 9, 9] [7, 7, 7] [0, 0, 0] [1, 1, 1]
ย
์ ์ฝ๋๋
map()
์ ํตํด List
๋ฐ์ดํฐ๋ฅผ ์์ฑํ๊ณ , ์ด๋ฅผ forEach()
์์ ํ๋ํ๋ ์ถ๋ ฅํ๋ ์ฝ๋์ด๋ฉฐ, println()
ํจ์์๋ ์์ฑํ List
ํ์
์ ๋ฐ์ดํฐ๊ฐ ๋ค์ด๊ฐ๊ฒ ๋๊ฒ ๋ค.ย
์ด ๋, ํ์์ ์ํด
List
๋ด๋ถ์ Elements๋ฅผ ๋ฐ๋ก Stream Pipeline์์ ์ฌ์ฉํ๊ณ ์ ํ๋ค๋ฉด ์ด๋ป๊ฒ ํด์ผ ํ ๊น?ย
๋ญ ์ฌ๋ฌ ๋ฐฉ๋ฒ์ด ์๊ฒ ์ผ๋...
map()
๋์ flatMap()
์ ์ฌ์ฉํ๋ ๋ฐฉ์์ผ๋ก ๊ตฌํํ๋ค๋ฉด ์๊ฐ๊ณผ๋ ๋ค๋ฅธ ๊ฒฐ๊ณผ๋ฅผ ๋ง์ฃผํ ๊ฒ์ด๋ค.ย
public class Main { public static void main(String[] args) { Stream.of("0123456789".split("")) .parallel() .flatMap(Main::genStringListStream) // <-- #2 .forEach(System.out::println); // <-- #3 } private static List<String> genList(String contents) { return Arrays.asList( String.valueOf(new char[10]).replaceAll("\0", contents).split("")); } private static Stream<String> genStringListStream(String contents) { return genList(contents).parallelStream(); } }
ย
์ ์ฝ๋๋ฅผ ์คํํ๋ฉด ์ด๋ ํ ๊ฒฐ๊ณผ๊ฐ ๋์ฌ๊น.
5 2 1 1 0 8 ...
๋ญ ์ด๋ ๊ฒ ์ถ๋ ฅ์ด ๋ ๊น? ์ ํ ์๋๋ค. ๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ๋ค.ย
// output 5 5 5 2 2 2 6 6 6 8 8 8 9 9 9 7 7 7 3 3 3 4 4 4 0 0 0 1 1 1
ย
๋ถ๋ช
ํ
Stream<String>
ํ์
์ผ๋ก ๋ฐํํ์์๋ ๋ถ๊ตฌํ๊ณ , List
๋จ์๋ก ์ถ๋ ฅ์ด ๋์ด๋ฒ๋ฆฐ๋ค. ๋ฌผ๋ก ์ด ๋ println()
ํจ์์ ๋ค์ด๊ฐ๋ ๋ฐ์ดํฐ๋ String
ํ์
์ด๋ค.Why
์ ์ด๋ฌํ ๊น? ์๊ฐํด๋ณด์.
ย
์ผ๋จ
flatMap()
๋ฉ์๋์ ์คํ์ ๋ณด๋ฉด, ์ธ์(Arguments)๋ก ์ ๋ฌ๋๋ ํจ์(Function
)๋ ๋ฐ๋์ Stream
ํ์
์ ๋ฐ์ดํฐ๋ฅผ ๋ฐํํ๋๋ก ๋ช
์๊ฐ ๋์ด ์์ผ๋ฉฐ, ๋ฐ๋ผ์ genStringListStream()
ํจ์ ์ญ์ ์ด์ ๋ง์ถฐ String
ํ์
์ Stream
์ ๋ฐํํ๋๋ก ์ฝ๋๋ฅผ ๊ตฌํํ๋ค.ย
์ด๊ฒ ์ด๋ ํ ๊ฒ์ ์๋ฏธํ ๊น.
ย
์,
Stream
์ Elements Sequence๋ฅผ ๋ค๋ฃจ๊ธฐ ์ํด ์กด์ฌํ๋ค. ๊ทธ๋ฆฌ๊ณ flatMap()
๋ฉ์๋๋ ์ธ์๋ก ์ ๋ฌ๋๋ ํจ์์ ๋ฐํ์ธ Stream
. ๋ค์๋งํด Elements Sequence ๋ด๋ถ์ Element๋ฅผ ์ดํ์ Stream Pipeline์์ ์ฌ์ฉํ ์ ์๋๋ก Flatten ํ๋ ์ญํ ์ ์ํํ ๊ฒ์ด๋ค.ย
๊ทธ๋ฌ๋ ์ค์ ๋ก๋ ๊ทธ๋ ๊ฒ ๋์ํ์ง ์๋๋ค.
flatMap()
์ ๊ตฌํ ์ฝ๋๋ฅผ ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์๋ฐ,ย
@Override public final <R> Stream<R> flatMap( Function<? super P_OUT, ? extends Stream<? extends R>> mapper ) { // ... @Override public void accept(P_OUT u) { try (Stream<? extends R> result = mapper.apply(u)) { if (result != null) { if (!cancellationRequestedCalled) { result.sequential().forEach(downstream); // <-- #1 } else { Spliterator<? extends R> s = result.sequential().spliterator(); do { } while (!downstream.cancellationRequested() && s.tryAdvance(downstream)); } } } } // ... }
ย
์ฝ๋์ #1 ๋ถ๋ถ์ ๋ณด๋ฉด ์ ์ ์๋ฏ์ด, ์ค์ ๋ก Flatten์ ํด์ฃผ๋ ๊ฒ์ด ์๋๋ผ ๊ทธ์ Stream์ ๋ํด
forEach()
๋ฅผ ํ๋๋ก ๊ตฌํํ์ ๋ฟ์ด๋ค.ย
๊ทธ๋๋ Parallel Stream์ผ๋ก ๋ช
์ํ์ผ๋ Parallelํ๊ฒ ๋์ํ์ง ์์๊น?
ย
๋ฌผ๋ก ์ด ์ญ์ ์๋๋ค. #1์์
sequential()
๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ณด์ผํ
๋ฐ, ์ด ๋ฉ์๋๋ Parallel์ ๋นํ์ฑํ ์ํค๋ ์์
์ ๋ด๋นํ๊ณ ์๊ธฐ ๋๋ฌธ์... (๋ฌธ์, ์ฝ๋)ย
์ ๋ฆฌํด์ ์ฝ๊ฒ ๋งํ์๋ฉด, ์ฝ๋์ #2 ๋ถ๋ถ์์๋
String
๋จ์๋ก Stream Pipeline์ด ์งํ๋์์ผ๋, #3 ๋ถ๋ถ์์๋ List
๋จ์๋ก Stream์ด ์งํ๋๋ค๋ ๋ง์ด๋ค.ย
๋ฐ๋ผ์ ์์ ๊ฐ์ด Element ๋จ์๊ฐ ์๋
List
๋จ์๋ก Parallel Stream์ด ์งํ๋๋ฉฐ, ์ด๋ ์ํ๋ ๋ฐฉ์์ธ Element ๋จ์์ Parallel Stream๊ณผ๋ ๊ฑฐ๋ฆฌ๊ฐ ๋งค์ฐ ๋งค์ฐ ๋งค์ฐ ๋งค์ฐ ๋งค์ฐ ๋ฉ๋ค.ย
์ฐธ๊ณ ๋ก ๋ค์ ๋ ์ฝ๋ ์ญ์ ์ํ๋ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฌ์ฃผ์ง ๋ชปํ๋ค.
ย
public class Main { public static void main(String[] args) { Stream.of("0123456789".split("")) .parallel() .flatMap(Main::genStringListStream) .parallel() .forEach(System.out::println); } private static List<String> genList(String contents) { return Arrays.asList( String.valueOf(new char[10]).replaceAll("\0", contents).split("")); } private static Stream<String> genStringListStream(String contents) { return genList(contents).parallelStream(); } }
// output 5 5 5 6 6 6 8 8 8 9 9 9 7 7 7 2 2 2 3 3 3 4 4 4 0 0 0 1 1 1
ย
public class Main { public static void main(String[] args) { Stream.of("0123456789".split("")) .parallel() .flatMap(Main::genListStream) .forEach(System.out::println); } private static List<String> genList(String contents) { return Arrays.asList( String.valueOf(new char[10]).replaceAll("\0", contents).split("")); } private static Stream<List<String>> genListStream(String contents) { return Stream.of(genList(contents)).parallel(); } }
// output [2, 2, 2] [5, 5, 5] [6, 6, 6] [8, 8, 8] [9, 9, 9] [7, 7, 7] [0, 0, 0] [1, 1, 1] [3, 3, 3] [4, 4, 4]
Conclusion
์ํ๊น๊ฒ๋ ํ์ฌ๋ก์ ์ด๋ฅผ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ์... ๊ฒฐ๊ตญ ์์ฑํ
List
์ ๋ํ Stream
์ ์์ฑํ๊ณ , ์ด์ ๋ํด Parallel Stream์ ์งํํ๋๋ก ๊ตฌํํ๋ ๋ฐฉ๋ฒ ํ๋ ๋ฟ์ด๋ค.ย
์๋ฌดํผ, ์ด์ ๊ฐ์ด Java Stream์
flatMap()
๋ฉ์๋๋ ์ค์ ๋ก Flat-Map์ ์งํํ์ง ์์์ ์ผ๋ํด ๋๊ณ ๊ฐ๋ฐ์ ํ๋๋ก ํ์. ์ฆ, flatMap()
์ Flat-Map์ด ์๋๋ค.ย