'flatMap()' โ‰  'Flat Map' in Parallel-Stream
๐Ÿ“„

'flatMap()' โ‰  'Flat Map' in Parallel-Stream

Created
Dec 31, 2021 11:20 AM
Tags
java
ย 
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 ํƒ€์ž…์ด๋‹ค.
ย 
์™œ ์ด๋Ÿฌํ• ๊นŒ? ์ƒ๊ฐํ•ด๋ณด์ž.
ย 
์ผ๋‹จ 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) {
                  
ย 
์ฝ”๋“œ์˜ #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]
ย 
์•ˆํƒ€๊น๊ฒŒ๋„ ํ˜„์žฌ๋กœ์„œ ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์€... ๊ฒฐ๊ตญ ์ƒ์„ฑํ•œ List ์— ๋Œ€ํ•œ Stream ์„ ์ƒ์„ฑํ•˜๊ณ , ์ด์— ๋Œ€ํ•ด Parallel Stream์„ ์ง„ํ–‰ํ•˜๋„๋ก ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ• ํ•˜๋‚˜ ๋ฟ์ด๋‹ค.
ย 
์•„๋ฌดํŠผ, ์ด์™€ ๊ฐ™์ด Java Stream์˜ flatMap() ๋ฉ”์„œ๋“œ๋Š” ์‹ค์ œ๋กœ Flat-Map์„ ์ง„ํ–‰ํ•˜์ง€ ์•Š์Œ์„ ์—ผ๋‘ํ•ด ๋‘๊ณ  ๊ฐœ๋ฐœ์„ ํ•˜๋„๋ก ํ•˜์ž. ์ฆ‰, flatMap() ์€ Flat-Map์ด ์•„๋‹ˆ๋‹ค.
ย 

Loading Comments...