Skip to content

Latest commit

ย 

History

History
304 lines (248 loc) ยท 13.4 KB

File metadata and controls

304 lines (248 loc) ยท 13.4 KB

์ŠคํŠธ๋ฆผ

๋žŒ๋‹ค๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ์ˆ  ์ค‘ ํ•˜๋‚˜๋กœ ์ผ์ข…์˜ ๋ฌดํ•œํ•œ ๋ฐ์ดํ„ฐ์˜ ํ๋ฆ„. ๋ฐฐ์—ด๋˜๋Š” ์ปฌ๋ ‰์…˜, Map๊ณผ ๊ฐ™์€ ์ž๋ฃŒ๊ตฌ์กฐ๋“ค์„ ํ•˜๋‚˜์˜ ๋ฐ์ดํ„ฐํ๋ฆ„์œผ๋กœ ๋งŒ๋“ฆ์œผ๋กœ์„œ ํ•จ์ˆ˜ ์—ฌ๋Ÿฌ๊ฐœ๋ฅผ chaningํ•˜์—ฌ ์ฝ”๋“œ์˜ ์–‘์„ ์ค„์ด๊ณ  ๊ฐ„๊ฒฐํ•˜๊ฒŒ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค.


ํŠน์ง•

1. ๋ณ‘๋ ฌ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ

ํ•œ๊ฐ€์ง€ ์ž‘์—…์— ๋Œ€ํ•ด ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๋กœ ๋‚˜๋ˆ„์–ด ๋ณ‘๋ ฌ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ณ  ๊ฒฐ๊ณผ๋“ค์„ ํ•ฉํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ๋ณ‘๋ ฌ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•˜๊ณ , ์ด๋•Œ ์ž๋ฐ”๋Š” ForkJoinPool ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ด์šฉํ•ด์„œ ๋ณ‘๋ ฌ์ฒ˜๋ฆฌ๋ฅผ ํ•œ๋‹ค.

ForkJoinPool? Fork(Task๋ฅผ ์ž˜๊ฒŒ ์ชผ๊ฐœ๋Š” ๊ฒƒ)๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ  ํ•ด๋‹น Pool์— ์žˆ๋Š” ์Šค๋ ˆ๋“œ๋“ค์ด task๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  join์„ ํ†ตํ•ด ํ•ฉ์นœ๋‹ค. ์ด๋•Œ ForkJoinPool์—๋Š” task๊ฐ€ ์กด์žฌํ•˜๋Š” queue๊ฐ€ ์žˆ๊ณ , ์Šค๋ ˆ๋“œ๋“ค์ด ์ด queue์—์„œ task๋ฅผ ํ• ๋‹น๋ฐ›์•„ ์ž์‹ ์˜ queue์— ์ ์žฌํ•ด๊ฐ€๋ฉฐ ์ฒ˜๋ฆฌํ•˜๋Š”๋ฐ ๋†€๊ณ ์žˆ๋Š” ์Šค๋ ˆ๋“œ๊ฐ€ ์กด์žฌํ•œ๋‹ค๋ฉด ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ์˜ queue์—์„œ task๋ฅผ stealํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ๋™์ž‘ํ•˜๋Š” Work-Stealing๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์ด์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— task๊ฐ€ ํ•˜์œ„ task๋ฅผ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜ small task๊ฐ€ ๋งŽ์„ ๊ฒฝ์šฐ ํšจ๊ณผ์ ์ด๋‹ค.

public class Ex{
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1,2,4,51,2,3);
        list.parallelStream().forEach(i->System.out.println(i+ " : " + Thread.currentThread().getName()));
    }
}

//print
2 : ForkJoinPool.commonPool-worker-3
51 : main
3 : ForkJoinPool.commonPool-worker-5
1 : ForkJoinPool.commonPool-worker-13
4 : ForkJoinPool.commonPool-worker-9
2 : ForkJoinPool.commonPool-worker-7

parallelStream์„ ์ด์šฉํ•˜๋ฉด ์‰ฝ๊ฒŒ ๋ณ‘๋ ฌ์ŠคํŠธ๋ฆผ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

public class Ex{
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1,2,4,51,2,3);
        list.parallelStream()
                .sequential().forEach(i->System.out.println(i+ " : " + Thread.currentThread().getName()));
    }
}

//print
1 : main
2 : main
4 : main
51 : main
2 : main
3 : main

sequential()๋ฅผ ์ด์šฉํ•˜๋ฉด ๋‹ค์‹œ ์‹œํ€€์…œ ์ŠคํŠธ๋ฆผ์œผ๋กœ ๋ณ€๊ฒฝ๋„ ๊ฐ€๋Šฅํ•˜๋‹ค.


+) Pool Size ์กฐ์ ˆ๋ฐฉ๋ฒ•

  1. property
 public static void main(String[] args) {
        System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism","4");
        List<Integer> list = Arrays.asList(1,2,4,51,2,3);
        list.parallelStream().forEach(i->System.out.println(i+ " : " + Thread.currentThread().getName()));

    }
  1. ForkJoinPool ๊ฐ์ฒด ์ด์šฉ
 public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1,2,4,51,2,3);
         ForkJoinPool pool = new ForkJoinPool(2);
         pool.submit(() -> list.parallelStream().sequential().forEach(i->System.out.println(i+ " : " + Thread.currentThread().getName()))).get();
    }

ForkJoinPool์ƒ์„ฑ์ž ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ size๋ฅผ ์ „๋‹ฌํ•˜๊ณ  submit()๋ฉ”์„œ๋“œ์— ๋žŒ๋‹ค๋กœ ์ž‘์—…ํ•  ๋‚ด์šฉ์„ ์ •์˜ํ•ด์ฃผ๊ณ  get()์„ ํ†ตํ•ด terminate()ํ•ด์ฃผ์–ด์•ผ ์‹คํ–‰์ด ๋œ๋‹ค.

  1. default Pool size ๋ณ€๊ฒฝ
-Djava.util.concurrent.ForkJoinPool.common.parallelism=16

build์‹œ์— ์œ„ ์˜ต์…˜์œผ๋กœ ๊ธฐ๋ณธ ํ’€ ์‚ฌ์ด์ฆˆ๋ฅผ ๋ณ€๊ฒฝ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.


๋‹จ์ 

์œ„์—์„œ ์„ค๋ช…ํ•œ๊ฒƒ๊ณผ ๊ฐ™์ด ForkJoinPool ํŠน์„ฑ์ƒ task๋ฅผ ๋ถ„ํ• ํ• ๋•Œ(fork) ๊ท ๋“ฑํ•˜๊ฒŒ ๋ถ„๋ฐฐ๋ฅผํ•˜๊ฒŒ ๋˜๋Š”๋ฐ ์ด๋•Œ ์ด ๋ถ„ํ• ํ•˜๋Š” ์ž‘์—…์˜ ๋น„์šฉ์ด ๋†’๊ฒŒ ๋˜๋ฉด ์˜คํžˆ๋ ค ์„ฑ๋Šฅ์ด ์•ˆ์ข‹์„ ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์ด๋ฏธ ์‚ฌ์ด์ฆˆ๋ฅผ ์•Œ๊ณ  ์žˆ๋Š” ArrayList๊ฐ™์€ ๊ฒฝ์šฐ๋Š” ๋ถ„ํ• ํ•˜๋Š” ์ž‘์—…์ด ๋น ๋ฅผ ์ˆ˜ ์žˆ์ง€๋งŒ ์‚ฌ์ด์ฆˆ๋ฅผ ๋ชจ๋ฅด๋Š” LinkedList๊ฐ™์€ ๊ฒฝ์šฐ์—๋Š” ์ˆœ์ฐจ์ž‘์—…๊ณผ ๊ฐ™๊ฑฐ๋‚˜ ๋” ๋А๋ฆด ์ˆ˜๊ฐ€ ์žˆ๋‹ค.

๋ณ‘๋ ฌ๋กœ ์ฒ˜๋ฆฌ๋˜๋Š” ์ž‘์—…์ด ๋…๋ฆฝ์ ์ด์ง€ ์•Š๋‹ค๋ฉด ์ด๋„ ์˜คํžˆ๋ ค ์„ฑ๋Šฅ์— ์•ˆ์ข‹์„ ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด sorted()/distinct()์™€ ๊ฐ™์€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ• ๋•Œ๋Š” ๋‚ด๋ถ€์˜ ์ƒํƒœ์— ๋Œ€ํ•œ ๋ณ€์ˆ˜๋ฅผ ์ž‘์—…์ด ๊ณต์œ ํ•ด์•ผ์ง€๋งŒ ๊ฐ€๋Šฅํ•œ ์ž‘์—…์ด๋ฏ€๋กœ lock์˜ ์ž‘์—…์ด ์ถ”๊ฐ€๋กœ ๋ฐœ์ƒํ•˜๊ณ  ์Šค๋ ˆ๋“œ๊ฐ€ ๋Œ€๊ธฐํ•˜๋Š” ์ƒํ™ฉ์ด ์ƒ๊ธฐ๊ธฐ ๋•Œ๋ฌธ์— ์ˆœ์ฐจ์ ์œผ๋กœ ์‹คํ–‰ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋” ํšจ๊ณผ์ ์ผ ์ˆ˜ ์žˆ๋‹ค.


2. ์ง€์—ฐ์—ฐ์‚ฐ์„ ํ†ตํ•œ ์„ฑ๋Šฅ ํ–ฅ์ƒ

๋‚ด์šฉ์€ ์ง€๋‚œ์ฃผ ์ •๋ฆฌํ–ˆ๋˜ ๋‚ด์šฉ์ค‘ ๋žŒ๋‹ค์˜ ์ง€์—ฐ์—ฐ์‚ฐ๊ณผ ๋™์ผํ•œ ๋‚ด์šฉ์ด๋‹ค.

List<Integer> list = Arrays.asList(1,2,4,51,2,3);

long result1 = list.stream().map(i -> {
    System.out.println(i);
    return i+1;
}).skip(3).count();
System.out.println("result 1 : " + result1);

long result2 = list.stream().skip(3).map(i -> {
    System.out.println(i);
    return i+1;
}).count();
System.out.println("result 1 : " + result2);

//print
1
2
4
51
2
3
result 1 : 3

51
2
3
result 1 : 3

์ถ”๊ฐ€์ ์œผ๋กœ ์ค‘๊ฐ„์—ฐ์‚ฐ์˜ ์ˆœ์„œ์— ๋”ฐ๋ผ ์œ„์ฒ˜๋Ÿผ ๋ถˆํ•„์š”ํ•œ ์—ฐ์‚ฐ์„ ๋ง‰์•„ ์„ฑ๋Šฅํ–ฅ์ƒ์„ ๊พ€ํ•  ์ˆ˜ ์žˆ๊ธฐ๋•Œ๋ฌธ์— ์ค‘๊ฐ„์—ฐ์‚ฐ์˜ ์ˆœ์„œ๋„ ์‹ ๊ฒฝ์„ ์จ์ฃผ๋ฉด ์ข‹๋‹ค.


3. ์ง€์—ฐ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ

public static void main(String[] args) {
    List<Integer> list = Arrays.asList(1,2,4,51,2,3);
    Stream<Integer> stream = list.stream().peek(System.out::println);

}

//bytecode
L1
    LINENUMBER 12 L1
    ALOAD 1
    INVOKEINTERFACE java/util/List.stream ()Ljava/util/stream/Stream; (itf)
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    DUP
    INVOKESTATIC java/util/Objects.requireNonNull (Ljava/lang/Object;)Ljava/lang/Object;
    POP
    INVOKEDYNAMIC accept(Ljava/io/PrintStream;)Ljava/util/function/Consumer; [
      // handle kind 0x6 : INVOKESTATIC
      java/lang/invoke/LambdaMetafactory.metafactory(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
      // arguments:
      (Ljava/lang/Object;)V, 
      // handle kind 0x5 : INVOKEVIRTUAL
      java/io/PrintStream.println(Ljava/lang/Object;)V, 
      (Ljava/lang/Integer;)V
    ]
    INVOKEINTERFACE java/util/stream/Stream.peek (Ljava/util/function/Consumer;)Ljava/util/stream/Stream; (itf)
    ASTORE 2

์œ„๋ฅผ ๋Œ๋ ค๋ณด๋ฉด print๊ฐ€ ๋˜์ง€ ์•Š์€ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋Š”๋ฐ Stream์€ ์ข…๋ฃŒ์—ฐ์‚ฐ์ด ์ˆ˜ํ–‰๋ ๋•Œ๊นŒ์ง€ ์ค‘๊ฐ„์—ฐ์‚ฐ์€ ์‹œ์ž‘ํ•˜์ง€ ์•Š๊ณ  ํ•˜๋‚˜์˜ Streamํ˜•ํƒœ๋กœ ์ €์žฅ์ด ๋˜์–ด ๋ฏธ๋ฆฌ Stream์„ ์„ ์–ธํ•ด๋‘๊ณ  ๋‚˜์ค‘์— ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

byte์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด Stremaํ˜•ํƒœ๋ฅผ ์ฐธ์กฐํƒ€์ž…์œผ๋กœ ์ €์žฅํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค .(ASTORE)


4. ์žฌ์‚ฌ์šฉ ๋ถˆ๊ฐ€๋Šฅ

์ŠคํŠธ๋ฆผ์€ ์ข…๋ฃŒ์—ฐ์‚ฐ์„ ํ•˜์ง€ ์•Š๋Š” ์ด์ƒ ๊ทธ์ „๊นŒ์ง€๊ฐ€ ํ•˜๋‚˜์˜ ์ธ์Šคํ„ด์Šค๋กœ์จ ๊ณ„์† ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜์ง€๋งŒ ์ข…๋ฃŒ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•˜๋ฉด ์žฌ์‚ฌ์šฉ์ด ๋ถˆ๊ฐ€ํ•˜๊ฒŒ ๋˜๋Š”๋ฐ ์ด๋Š” ์ŠคํŠธ๋ฆผ์€ ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๊บผ๋‚ด์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ์šฉ๋„์ด์ง€ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ๋ชฉ์ ์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1,2,4,51,2,3);

       Stream<Integer> stream = list.stream().map(i -> i+1);

       stream.count();
       stream.forEach(System.out::println);     //Exception ๋ฐœ์ƒ : java.lang.IllegalStateException: stream has already been operated upon or closed
}

Stream์€ AutoCloseable์„ ์ƒ์†๋ฐ›์€ BaseStream์„ ์ƒ์†๋ฐ›์•„ close()๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์–ด ์ข…๋ฃŒ์—ฐ์‚ฐ์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด ์šฐ๋ฆฌ๊ฐ€ ๋ช…์‹œํ•˜์ง€ ์•Š์•„๋„ ๋‚ด๋ถ€์ ์œผ๋กœ close()๋ฅผ ์‹œ์ผœ์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ์žฌ์‚ฌ์šฉ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.

L1
    LINENUMBER 13 L1
    ALOAD 1
    INVOKEINTERFACE java/util/List.stream ()Ljava/util/stream/Stream; (itf)
    INVOKEDYNAMIC apply()Ljava/util/function/Function; [
      // handle kind 0x6 : INVOKESTATIC
      java/lang/invoke/LambdaMetafactory.metafactory(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
      // arguments:
      (Ljava/lang/Object;)Ljava/lang/Object;, 
      // handle kind 0x6 : INVOKESTATIC
      ex/Ex.lambda$main$0(Ljava/lang/Integer;)Ljava/lang/Integer;, 
      (Ljava/lang/Integer;)Ljava/lang/Integer;
    ]
    INVOKEINTERFACE java/util/stream/Stream.map (Ljava/util/function/Function;)Ljava/util/stream/Stream; (itf)
    ASTORE 2
   L2
    LINENUMBER 15 L2
    ALOAD 2
    INVOKEINTERFACE java/util/stream/Stream.count ()J (itf)
    POP2
   L3
    LINENUMBER 16 L3
    ALOAD 2
    INVOKEDYNAMIC compare()Ljava/util/Comparator; [
      // handle kind 0x6 : INVOKESTATIC
      java/lang/invoke/LambdaMetafactory.metafactory(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
      // arguments:
      (Ljava/lang/Object;Ljava/lang/Object;)I, 
      // handle kind 0x5 : INVOKEVIRTUAL
      java/lang/Integer.compareTo(Ljava/lang/Integer;)I, 
      (Ljava/lang/Integer;Ljava/lang/Integer;)I
    ]
    INVOKEINTERFACE java/util/stream/Stream.max (Ljava/util/Comparator;)Ljava/util/Optional; (itf)
    POP

์•ž์„œ ์ž‘์„ฑํ•œ ์ฝ”๋“œ์˜ ๋ฐ”์ดํŠธ์ฝ”๋“œ ์ผ๋ถ€๋ถ„์ธ๋ฐ, ์•ž์„œ ์ž‘์„ฑํ•œ Stream์„ ์ฐธ์กฐ์˜์—ญ 2์— ์ €์žฅํ•˜๊ณ , count()๋ฉ”์„œ๋“œ์—์„œ ์ด๋ฅผ loadํ•˜๊ณ  popํ•˜๋Š” ๊ฒƒ์„ ๋ณผ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ max()๋ฉ”์„œ๋“œ์—์„œ ์ด popํ•œ ์ฐธ์กฐ์˜์—ญ 2๋ฅผ ๋‹ค์‹œ loadํ•˜๋ ค๊ณ  ํ•˜๋‹ˆ ๋Ÿฐํƒ€์ž„์— ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์ด๋‹ค.



๋ฉ”์„œ๋“œ ์ข…๋ฅ˜

1. ์ƒ์„ฑ

์ŠคํŠธ๋ฆผ ์ธ์Šคํ„ด์Šค ์ƒ์„ฑํ•˜๋Š” ๋ฉ”์„œ๋“œ

  • Arrays.stream(๋ฐฐ์—ดํƒ€์ž… ๋ณ€์ˆ˜) : ๋ฐฐ์—ด์„ Stream ํƒ€์ž… ๊ฐ์ฒด๋กœ ์ƒ์„ฑ
  • collection.stream() : Collectionํƒ€์ž…์˜ ๊ฐ์ฒด(Collection, List, Set)๋ฅผ Stream ํƒ€์ž… ๊ฐ์ฒด๋กœ ์ƒ์„ฑ
  • Stream.empty() : ๋น„์–ด์žˆ๋Š” Stream() ๊ฐ์ฒด
  • Stream.builder().add()...build() : ๋นŒ๋”๋ฅผ ์ด์šฉํ•œ Stream ์ƒ์„ฑ
  • Stream.generate(() -> {}).limit() : ๋žŒ๋‹ค๋ฅผ ์ด์šฉํ•˜์—ฌ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๋žŒ๋‹ค์˜ return๊ฐ’์ด ๋“ค์–ด์žˆ๋Š” Stream์„ ์ƒ์„ฑํ•œ๋‹ค. ์ด๋•Œ ๋ฌดํ•œํžˆ ์ƒ์„ฑํ•˜๊ธฐ ๋•Œ๋ฌธ์— limit๋ฉ”์„œ๋“œ๋กœ ์ œํ•œ์„ ์ฃผ์–ด์•ผ ํ•œ๋‹ค.
  • Stream.iterate(startValue, () -> {}).limit() : ์ดˆ๊ธฐ๊ฐ’๋ถ€ํ„ฐ ํ•ด๋‹น ๊ฐ’์„ input์œผ๋กœ ํ•˜๋Š” ๋žŒ๋‹ค๋ฅผ ๋ฐ˜๋ณตํ•˜์—ฌ ๋‚˜์˜จ ๊ฐ’์œผ๋กœ Stream์„ ์ƒ์„ฑ
  • IntStream.reange(1,5).boxed() : IntStream์„ ์ƒ์„ฑํ›„ boxed()๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด Stream ์ธ์Šคํ„ด์Šค๋กœ ๋ฐ˜ํ™˜
  • Random().ints().boxed() : ๋žœ๋คํ•œ int๊ฐ’์„ ์ด์šฉํ•ด Stream ์ƒ์„ฑ
  • "String".chars() : IntStream์„ ๋ฐ˜ํ™˜
    • char๋“ค์€ ascii ๊ฐ’์œผ๋กœ ํ•˜๋‚˜์˜ ์ˆซ์ž๋กœ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— IntStream์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
  • list.parallelStream() : ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ

2. ๊ฐ€๊ณต

ํ•„ํ„ฐ๋ง, ๋งตํ•‘๊ณผ ๊ฐ™์ด ์–ด๋– ํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋งŒ๋“ค์–ด๊ฐ€๋Š” ์ค‘๊ฐ„ ์ž‘์—…๋“ค์˜ ๋ฉ”์„œ๋“œ ( Intermediate operations )

  • filter(Predicate) : Predicate์˜ ๋ฐ˜ํ™˜๊ฐ’์ด true์ธ ๋ฐ์ดํ„ฐ๋งŒ ์„ ํƒ

  • distinct() : ์ค‘๋ณต๋œ ๋ฐ์ดํ„ฐ ์ œ๊ฑฐ

  • map(Function<T,R>) : ๋ฐ์ดํ„ฐ๋“ค์„ ๊ฐ€๊ณตํ•˜์—ฌ ๋‹ค๋ฅธ ๊ฐ’์œผ๋กœ ๋ณ€๊ฒฝํ•˜๊ณ ์ž ํ• ๋•Œ ์‚ฌ์šฉ

  • flatMap(Function<T, Stream>) : ์ค‘์ฒฉ๊ตฌ์กฐ๋ฅผ ์ œ๊ฑฐํ•˜๊ณ  ๋‹จ์ผ ์ปฌ๋ ‰์…˜์œผ๋กœ ๋งŒ๋“ค์–ด map์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰(flattening)

    public static void main(String[] args) {
        List<String> list = Arrays.asList("Hello", "World");
        List<String[]> result = list.stream().map(s -> s.split("")).distinct().collect(Collectors.toList());
    
        for (String[] strings : result) {
            System.out.println(Arrays.toString(strings));
        }
    }
    
    //print
    [H, e, l, l, o]
    [W, o, r, l, d]

    ๋งŒ์ผ ๋ฌธ์ž์—ด์ด ๋“ค์–ด์žˆ๋Š” ๋ฐฐ์—ด์—์„œ ๋ชจ๋“  ๋ฌธ์ž์—ด์— ๋Œ€ํ•ด ์‚ฌ์šฉ๋œ ์•ŒํŒŒ๋ฒณ๋“ค๋งŒ ์ฐพ์•„๋‚ด๋Š” ํ•จ์ˆ˜๋ฅผ ๊ตฌ์„ฑํ•œ๋‹ค๊ณ  ํ• ๋•Œ map()์„ ์ด์šฉํ•˜๋ฉด ์œ„์™€ ๊ฐ™์ด ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ค๊ฒŒ ๋œ๋‹ค.

    ์ด๋Š” ์•ŒํŒŒ๋ฒณ์„ ํ•˜๋‚˜ํ•˜๋‚˜ ์กฐํšŒํ•˜๊ธฐ ์œ„ํ•ด String์„ split()์„ ์ด์šฉํ•˜์—ฌ String๋ฐฐ์—ด๋กœ ํ•œ๋ฒˆ๋” ๋‚˜๋ˆ„๋Š” ๊ณผ์ •์—์„œ ์ž๋ฃŒ๊ตฌ์กฐ์˜ depth๊ฐ€ ํ•œ๋‹จ๊ณ„ ์ฆ๊ฐ€ํ•˜์—ฌ Hello World๋ผ๋Š” ๋‹จ์–ด์—์„œ distinct๊ฐ€ ์ˆ˜ํ–‰๋œ๊ฒŒ ์•„๋‹ˆ๋ผ Hello, World ๋”ฐ๋กœ ์ˆ˜ํ–‰๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋ฐ”๋กœ ์ด๋Ÿด๋•Œ flatMap์„ ์ด์šฉํ•˜๋ฉด ํ•œ๋‹จ๊ณ„ ์ค‘์ฒฉ๊ตฌ์กฐ๋ฅผ ๋ฒ—๊ฒจ๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

    public static void main(String[] args) {
        List<String> list = Arrays.asList("Hello", "World");
        List<String> result = list.stream().map(s -> s.split("")).flatMap(Arrays::stream).distinct().collect(Collectors.toList());
    
        for (String strings : result) {
            System.out.print(strings);
        }
    }
    
    //print
    HeloWrd
  • sorted(Comparator) : Comparator์„ ์ด์šฉํ•ด ๋ฐ์ดํ„ฐ ์ •๋ ฌ

  • peek(Consumer) : ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ  ๊ทธ์ € ์ˆœํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋กœ ์ค‘๊ฐ„์— ๊ฒฐ๊ณผ ํ™•์ธํ• 


3. ์ข…๋ฃŒ

์ตœ์ข…์ ์œผ๋กœ ๊ฒฐ๊ณผ๋ฅผ ๋งŒ๋“ค๊ณ  ๋ฐ˜ํ™˜ํ•จ์œผ๋กœ์จ chaining์„ ๋๋‚ด๋Š” ๋ฉ”์„œ๋“œ ( terminal operations )

  • ๋‹จ์ˆœ ๊ณ„์‚ฐ
    • count() : ์ด ๊ฐฏ์ˆ˜
    • sum() : ํ•ฉ
    • min() : ์ตœ์†Œ๊ฐ’
    • max() : ์ตœ๋Œ€๊ฐ’
    • avarage() : ํ‰๊ท ๊ฐ’
  • reduce() : ์ •์˜ํ•œ ๋กœ์ง์„ ๊ณ„์‚ฐ ํ›„ ๊ฒฐ๊ณผ ๋ฐ˜ํ™˜
    • reduce(BinaryOperator) : ๊ฐ ์š”์†Œ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋กœ์ง
    • reduce(T,BinaryOperator) : ๊ณ„์‚ฐ์„ ์œ„ํ•œ ์ดˆ๊ธฐ๊ฐ’ T๋ฅผ ๊ฐ€์ง€๊ณ  ๊ฐ ์š”์†Œ๋ฅผ ์ฒ˜๋ฆฌ
  • collect : ํŠน์ • ๋ฐ์ดํ„ฐํ˜•ํƒœ, ์ž๋ฃŒ๊ตฌ์กฐ๋กœ ๋ฐ”๊พธ์–ด์ฃผ๋Š” ํ•จ์ˆ˜
  • matching
    • anyMatch(Predicate) : ํ•˜๋‚˜๋ผ๋„ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” ์š”์†Œ๊ฐ€ ์žˆ์œผ๋ฉด true
    • allMAtch(Predicate) : ๋ชจ๋“  ์š”์†Œ๊ฐ€ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋ฉด true
    • noneMatch(Predicate) : ๋ชจ๋‘ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜์ง€ ์•Š์œผ๋ฉด ture
  • forEach() : ์š”์†Œ๋ฅผ ๋Œ๋ฉด์„œ ์‹คํ–‰ํ•˜๋Š” ๋ฉ”์„œ๋“œ





Reference

https://www.inflearn.com/course/the-java-java8/dashboard

https://dev-milk.tistory.com/5

https://futurecreator.github.io/2018/08/26/java-8-streams-advanced/