CHAP04 - Modern-Java-in-Action/Online-Study GitHub Wiki

  • SELECT name FROM dishes WHERE calorie < 400
    • SQL질의 μ–Έμ–΄μ—μ„œλŠ” μš°λ¦¬κ°€ κΈ°λŒ€ν•˜λŠ” 것이 무엇인지 직접 ν‘œν˜„ν•  수 μžˆλ‹€.
  • μ»¬λ ‰μ…˜μœΌλ‘œλ„ 이와 λΉ„μŠ·ν•œ κΈ°λŠ₯을 λ§Œλ“€ 수 μžˆμ§€ μ•Šμ„κΉŒ?
  • λ§Žμ€ μš”μ†Œλ₯Ό ν¬ν•¨ν•˜λŠ” μ»€λ‹€λž€ μ»¬λ ‰μ…˜μ€ μ–΄λ–»κ²Œ μ²˜λ¦¬ν•΄μ•Ό ν• κΉŒ?
    • μ„±λŠ₯을 높이렀면 λ©€ν‹°μ½”μ–΄ μ•„ν‚€ν…μ²˜λ₯Ό ν™œμš©ν•΄μ„œ λ³‘λ ¬λ‘œ μ»¬λ ‰μ…˜μ˜ μš”μ†Œλ₯Ό μ²˜λ¦¬ν•΄μ•Όν•œλ‹€.
    • ν•˜μ§€λ§Œ 병렬 처리 μ½”λ“œλ₯Ό κ΅¬ν˜„ν•˜λŠ” 것은 λ‹¨μˆœ 반볡 처리 μ½”λ“œμ— λΉ„ν•΄ λ³΅μž‘ν•˜κ³  μ–΄λ ΅λ‹€.
    • κ²Œλ‹€κ°€ λ³΅μž‘ν•œ μ½”λ“œλŠ” 디버깅도 μ–΄λ ΅λ‹€.

μŠ€νŠΈλ¦Όμ΄λž€ 무엇인가?

  • πŸ“Œ μŠ€νŠΈλ¦Όμ„ μ΄μš©ν•˜λ©΄
    • μ„ μ–Έν˜•(즉 , 데이터λ₯Ό μ²˜λ¦¬ν•˜λŠ” μž„μ‹œ κ΅¬ν˜„ μ½”λ“œ λŒ€μ‹  질의둜 ν‘œν˜„ν•  수 μžˆλ‹€.)으둜 μ»¬λ ‰μ…˜ 데이터λ₯Ό μ²˜λ¦¬ν•  수 μžˆλ‹€.
    • λ©€ν‹° μŠ€λ ˆλ“œ μ½”λ“œλ₯Ό κ΅¬ν˜„ν•˜μ§€ μ•Šμ•„λ„ 데이터λ₯Ό 투λͺ…ν•˜κ²Œ λ³‘λ ¬λ‘œ μ²˜λ¦¬ν•  수 μžˆλ‹€. (7μž₯μ—μ„œ μžμ„Ένžˆ)

예제 (filter , sort , λ°˜ν™˜)

  • μ €μΉΌλ‘œλ¦¬μ˜ μš”λ¦¬λͺ…을 λ°˜ν™˜ν•˜κ³  , 칼둜리λ₯Ό κΈ°μ€€μœΌλ‘œ μš”λ¦¬λ₯Ό μ •λ ¬ν•œλ‹€.

μžλ°” 7

  List<Dish> lowCaloricDishes = new ArrayList<>();
  for(Dish dish : menu){
      if(dish.getCalories() < 400){
          lowCaloricDishes.add(dish);
      }
  }
  Collections.sort(lowCaloricDishes , new Comparator<Dish>(){ // 읡λͺ…ν΄λž˜μŠ€λ‘œ μ •λ ¬
      public int compare(Dish dish1 , Dish dish2){
          return Integer.compare(dish1.getCalories() , dish2.getCalories());
      }
  });
  List<String> lowCaloricDishesName = new ArrayList<>();
  for(Dish dish : lowCaloricDishes){
      lowCaloricDishesName.add(dish.getName());
  }
  • lowCaloricDishesλŠ” μ»¨ν…Œμ΄λ„ˆ μ—­ν• λ§Œ ν•˜λŠ” 쀑간 λ³€μˆ˜λ‹€. (κ°€λΉ„μ§€ λ³€μˆ˜)
  • μžλ°” 8 μ—μ„œ μ΄λŸ¬ν•œ μ„ΈλΆ€ κ΅¬ν˜„μ€ 라이브러리 λ‚΄μ—μ„œ λͺ¨λ‘ μ²˜λ¦¬ν•œλ‹€.

βœ‹ Comparator와 Comparable

μžλ°” 8

  import static java.util.Comparator.comparing;
  import static java.util.stream.Collectors.toList;

  List<String> lowCaloricDishesName =
              menu.stream()
                  .filter(dish -> dish.getCalories() < 400)
                  .sorted(comparing(Dish::getCalories))
                  .map(Dish::getName)
                  .collect(toList());

  List<String> lowCaloricDishesName =
              menu.parallelStream() // 병렬 μ‹€ν–‰
                  .filter(dish -> dish.getCalories() < 400)
                  .sorted(comparing(Dish::getCalories))
                  .map(Dish::getName)
                  .collect(toList());
  • 7μž₯μ—μ„œ μ•„λž˜μ˜ ν•­λͺ©μ— λŒ€ν•΄ μ„€λͺ…ν•œλ‹€.
    • parallelStream()을 ν˜ΈμΆœν–ˆμ„ λ•Œ μ •ν™•νžˆ μ–΄λ–€ 일이 μΌμ–΄λ‚ κΉŒ?
    • μ–Όλ§ˆλ‚˜ λ§Žμ€ μŠ€λ ˆλ“œκ°€ μ‚¬μš©λ˜λŠ” 걸까?
    • μ–Όλ§ˆλ‚˜ μ„±λŠ₯이 μ’‹μ„κΉŒ?
  • μ„ μ–Έν˜•μœΌλ‘œ μ½”λ“œλ₯Ό κ΅¬ν˜„ν•˜μ—¬ λ³€ν•˜λŠ” μš”κ΅¬μ‚¬ν•­μ— μ‰½κ²Œ λŒ€μ‘ν•  수 μžˆλ‹€.
  • filter , sorted , map , collect 같은 μ—¬λŸ¬ λΉŒλ”© 블둝 연산을 μ—°κ²°ν•΄μ„œ λ³΅μž‘ν•œ 데이터 처리 νŒŒμ΄ν”„λΌμΈμ„ λ§Œλ“€ 수 μžˆλ‹€.
    • μœ„μ˜ 4κ°€μ§€ 연산은 κ³ μˆ˜μ€€ λΉŒλ”© λΈ”λ‘μœΌλ‘œ 이루어져 μžˆμœΌλ―€λ‘œ νŠΉμ • μŠ€λ ˆλ”© λͺ¨λΈμ— μ œν•œλ˜μ§€ μ•Šκ³  자유둭게 μ–΄λ–€ μƒν™©μ—μ„œλ“  μ‚¬μš©ν•  수 μžˆλ‹€.
  • πŸ“Œ 결과적으둜 데이터 처리 과정을 λ³‘λ ¬ν™”ν•˜λ©΄μ„œ μŠ€λ ˆλ“œμ™€ 락을 κ±±μ •ν•  ν•„μš”κ°€ μ—†λ‹€.

❗ 6μž₯ 슀트림으둜 데이터 μˆ˜μ§‘ 예제 맛보기

Map<Dish.Type , List<Dish>> dishesByType
           = menu.stream().collect(groupingBy(Dish::getType));
FISH = [prawns , salmon]
OTHER = [french fries , rice , season fruit , pizza]
MEAT = [pork , beef , chicken]

기타 라이브러리 : ꡬ아바 , μ•„νŒŒμΉ˜ , λžŒλ‹€μ œμ΄

  • μžλ°” ν”„λ‘œκ·Έλž˜λ¨Έκ°€ μ»¬λ ‰μ…˜μ„ μ œμ–΄ν•˜λŠ” 데 도움이 λ˜λŠ” λ‹€μ–‘ν•œ λΌμ΄λΈŒλŸ¬λ¦¬κ°€ μžˆλ‹€.
  • ꡬ글 ➜ ꡬ아바(Guava) λŠ” λ©€ν‹°λ§΅ , λ©€ν‹°μ…‹λ“± 좔가적인 μ»¨ν…Œμ΄λ„ˆ ν΄λž™μŠ€λ₯Ό μ œκ³΅ν•œλ‹€.
  • μ•„νŒŒμΉ˜ 곡톡 μ»¬λ ‰μ…˜ λΌμ΄λΈŒλŸ¬λ¦¬λ„ μœ„μ™€ λΉ„μŠ·ν•œ κΈ°λŠ₯을 μ œκ³΅ν•œλ‹€.
  • λžŒλ‹€μ œμ΄λŠ” ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ°μ—μ„œ μ˜κ°μ„ 받은 μ„ μ–Έν˜•μœΌλ‘œ μ»¬λ ‰μ…˜μ„ μ œμ–΄ν•˜λŠ” λ‹€μ–‘ν•œ μœ ν‹Έλ¦¬ν‹°λ₯Ό μ œκ³΅ν•œλ‹€.

슀트림 μ‹œμž‘ν•˜κΈ°

  • List<Dish> menu = Arrays.asList(...)
  List<Dish> menu = Arrays.asList(
                  new Dish("pork" , false , 800 , Dish.Type.MEAT),
                  new Dish("beef" , false , 700 , Dish.Type.MEAT),
                  new Dish("chicken" , false , 400 , Dish.Type.MEAT),
                  new Dish("french fries" , true , 530 , Dish.Type.OTHER),
                  new Dish("rice" , true , 350 , Dish.Type.OTHER),
                  new Dish("season fruit" , true , 120 , Dish.Type.OTHER),
                  new Dish("pizza" , true , 550 , Dish.Type.OTHER),
                  new Dish("prawns" , false , 300 , Dish.Type.FISH),
                  new Dish("salmon" , false , 450 , Dish.Type.FISH)
  );
  • public Class Dish{..}
public class Dish {
    private final String name;
    private final boolean vegetarian;
    private final int calories;
    private final Type type;

    public Dish(String name, boolean vegetarian, int calories , Type type) {
        this.name = name;
        this.vegetarian = vegetarian;
        this.calories = calories;
        this.type = type;
    }

    public String getName() {
        return name;
    }

    public boolean isVegetarian() {
        return vegetarian;
    }

    public int getCalories() {
        return calories;
    }

    public Type getType() {
        return type;
    }

    public enum Type {MEAT , FISH , OTHER}
}

μŠ€νŠΈλ¦Όμ΄λž€ , 데이터 처리 연산을 μ§€μ›ν•˜λ„λ‘ μ†ŒμŠ€μ—μ„œ μΆ”μΆœλœ μ—°μ†λœ μš”μ†Œλ‘œ μ •μ˜ν•  수 μžˆλ‹€.

  • μžλ°” 8 μ»¬λ ‰μ…˜μ—λŠ” μŠ€νŠΈλ¦Όμ„ λ°˜ν™˜ν•˜λŠ” streamλ©”μ„œλ“œκ°€ 좔가됐닀.
  • 슀트림의 μΈν„°νŽ˜μ΄μŠ€ μ •μ˜λŠ” java.util.stream.Stream μ°Έκ³ 
  1. μ—°μ†λœ μš”μ†Œ

    • μ»¬λ ‰μ…˜κ³Ό λ§ˆμ°¬κ°€μ§€λ‘œ μŠ€νŠΈλ¦Όμ€ νŠΉμ • μš”μ†Œ ν˜•μ‹μœΌλ‘œ 이루어진 μ—°μ†λœ κ°’ μ§‘ν•©μ˜ μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ œκ³΅ν•œλ‹€.
    • μ»¬λ ‰μ…˜μ˜ μ£Όμ œλŠ” 데이터이고 , 슀트림의 μ£Όμ œλŠ” 계산이닀.
  2. μ†ŒμŠ€

    • μŠ€νŠΈλ¦Όμ€ μ»¬λ ‰μ…˜ , λ°°μ—΄ , I/O μžμ›λ“±μ˜ 데이터 제곡 μ†ŒμŠ€λ‘œλΆ€ν„° 데이터λ₯Ό μ†ŒλΉ„ν•œλ‹€.
    • 리슀트둜 μŠ€νŠΈλ¦Όμ„ λ§Œλ“€λ©΄ 슀트림의 μš”μ†ŒλŠ” 리슀트의 μš”μ†Œμ™€ 같은 μˆœμ„œλ₯Ό μœ μ§€ν•œλ‹€.
  3. 데이터 처리 μ—°μ‚°

    • μŠ€νŠΈλ¦Όμ€ ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄μ—μ„œ 일반적으둜 μ§€μ›ν•˜λŠ” μ—°μ‚°κ³Ό λ°μ΄ν„°λ² μ΄μŠ€μ™€ λΉ„μŠ·ν•œ 연산을 μ§€μ›ν•œλ‹€.
    • 슀트림 연산은 순차적으둜 λ˜λŠ” λ³‘λ ¬λ‘œ μ‹€ν–‰ν•  수 μžˆλ‹€.
  4. νŒŒμ΄ν”„λΌμ΄λ‹

    • λŒ€λΆ€λΆ„μ˜ 슀트림 연산은 슀트림 연산끼리 μ—°κ²°ν•΄μ„œ μ»€λ‹€λž€ νŒŒμ΄ν”„λΌμΈμ„ ꡬ성할 수 μžˆλ„λ‘ 슀트림 μžμ‹ μ„ λ°˜ν™˜ν•œλ‹€.
    • κ·Έ 덕뢄에 laziness , short-circuiting같은 μ΅œμ ν™”λ„ 얻을 수 μžˆλ‹€. (5μž₯μ—μ„œ μ„€λͺ…)
    • μ—°μ‚° νŒŒμ΄ν”„λΌμΈμ€ 데이터 μ†ŒμŠ€μ— μ μš©ν•˜λŠ” λ°μ΄ν„°λ² μ΄μŠ€ μ§ˆμ˜μ™€ λΉ„μŠ·ν•˜λ‹€.
  5. λ‚΄λΆ€ 반볡

    • 반볡자λ₯Ό μ΄μš©ν•΄μ„œ λͺ…μ‹œμ μœΌλ‘œ λ°˜λ³΅ν•˜λŠ” μ»¬λ ‰μ…˜κ³Ό 달리 μŠ€νŠΈλ¦Όμ€ λ‚΄λΆ€ λ°˜λ³΅μ„ μ§€μ›ν•œλ‹€. (4.3.2절 μ—μ„œ μ„€λͺ…)

예제

  List<String> threeHighCaloricDishNames =
          menu.stream()
              .filter(dish -> dish.getCalories() > 300)
              .map(Dish::getName)
              .limit(3)
              .collect(toList());
  System.out.println(threeHighCaloricDishNames);
  // [pork, beef, chicken]

  1. menu에 stream() λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•΄μ„œ μŠ€νŠΈλ¦Όμ„ μ–»μ—ˆλ‹€.
    • 데이터 μ†ŒμŠ€λŠ” μš”λ¦¬ λ¦¬μŠ€νŠΈλ‹€.
    • μš”λ¦¬ λ¦¬μŠ€νŠΈλŠ” μ—°μ†λœ μš”μ†Œλ₯Ό μŠ€νŠΈλ¦Όμ— μ œκ³΅ν•œλ‹€.
  2. λ‹€μŒμœΌλ‘œ μŠ€νŠΈλ¦Όμ— filter , map , limit 둜 μ΄μ–΄μ§€λŠ” 일련의 데이터 처리 연산을 μ μš©ν•œλ‹€.
    • πŸ“Œ collectλ₯Ό μ œμ™Έν•œ λͺ¨λ“  연산은 μ„œλ‘œ νŒŒμ΄ν”„λΌμΈμ„ ν˜•μ„±ν•  수 μžˆλ„λ‘ μŠ€νŠΈλ¦Όμ„ λ°˜ν™˜ν•œλ‹€.
    • νŒŒμ΄ν”„λΌμΈμ€ μ†ŒμŠ€μ— μ μš©ν•˜λŠ” 질의 같은 μ‘΄μž¬λ‹€.
  3. λ§ˆμ§€λ§‰μœΌλ‘œ collectμ—°μ‚°μœΌλ‘œ νŒŒμ΄ν”„λΌμΈμ„ μ²˜λ¦¬ν•΄μ„œ κ²°κ³Όλ₯Ό λ°˜ν™˜ν•œλ‹€.

βœ‹ JAVAμ—μ„œ μ œκ³΅ν•˜λŠ” ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€


μ»¬λ ‰μ…˜κ³Ό 슀트림

  • 데이터λ₯Ό μ–Έμ œ κ³„μ‚°ν•˜λŠλƒκ°€ μ»¬λ ‰μ…˜κ³Ό 슀트림의 κ°€μž₯ 큰 차이닀.
  • μ»¬λ ‰μ…˜μ€ ν˜„μž¬ μžλ£Œκ΅¬μ‘°κ°€ ν¬ν•¨ν•˜λŠ” λͺ¨λ“ κ°’을 λ©”λͺ¨λ¦¬μ— μ €μž₯ν•˜λŠ” μžλ£Œκ΅¬μ‘°λ‹€.
    • 즉 , μ»¬λ ‰μ…˜μ˜ λͺ¨λ“  μš”μ†ŒλŠ” μ»¬λ ‰μ…˜μ— μΆ”κ°€ν•˜κΈ° 전에 κ³„μ‚°λ˜μ–΄μ•Ό ν•œλ‹€.
  • μŠ€νŠΈλ¦Όμ€ 이둠적으둜 μš”μ²­ν•  λ•Œλ§Œ μš”μ†Œλ₯Ό κ³„μ‚°ν•˜λŠ” κ³ μ •λœ μžλ£Œκ΅¬μ‘°λ‹€.
    • μŠ€νŠΈλ¦Όμ— μš”μ†Œλ₯Ό μΆ”κ°€ν•˜κ±°λ‚˜ μ œκ±°ν•  수 μ—†λ‹€.
    • πŸ“Œ μ‚¬μš©μžκ°€ μš”μ²­ν•˜λŠ” κ°’λ§Œ μŠ€νŠΈλ¦Όμ—μ„œ μΆ”μΆœν•œλ‹€λŠ” 것이 핡심이닀.
    • 게으λ₯΄κ²Œ λ§Œλ“€μ–΄μ§€λŠ” μ»¬λ ‰μ…˜κ³Ό κ°™λ‹€.

λ”± ν•œ 번만 탐색할 수 μžˆλ‹€.

  • λ°˜λ³΅μžμ™€ λ§ˆμ°¬κ°€μ§€λ‘œ ν•œ 번 νƒμƒ‰ν•œ μš”μ†Œλ₯Ό λ‹€μ‹œ νƒμƒ‰ν•˜λ €λ©΄ 초기 데이터 μ†ŒμŠ€μ—μ„œ μƒˆλ‘œμš΄ μŠ€νŠΈλ¦Όμ„ λ§Œλ“€μ–΄μ•Όν•œλ‹€.
    • 즉 , νƒμƒ‰λœ 슀트림의 μš”μ†ŒλŠ” μ†ŒλΉ„λœλ‹€.
    • μ»¬λ ‰μ…˜μ²˜λŸΌ 반볡 μ‚¬μš©ν•  수 μžˆλŠ” 데이터 μ†ŒμŠ€μ—¬μ•Όν•œλ‹€. 데이터 μ†ŒμŠ€κ°€ I/O 채널이라면 μ†ŒμŠ€λ₯Ό 반볡 μ‚¬μš©ν•  수 μ—†μœΌλ―€λ‘œ μƒˆλ‘œμš΄ μŠ€νŠΈλ¦Όμ„ λ§Œλ“€ 수 μ—†λ‹€.
    • μŠ€νŠΈλ¦Όμ€ 단 ν•œλ²ˆλ§Œ μ†ŒλΉ„ν•  수 μžˆλ‹€λŠ” 점을 λͺ…μ‹¬ν•˜μž!
  Stream<String> threeHighCaloricDishNames =
          menu.stream()
              .filter(dish -> dish.getCalories() > 300)
              .map(dish -> dish.getName())
              .limit(3);

  System.out.println(threeHighCaloricDishNames);
  System.out.println(threeHighCaloricDishNames);

  threeHighCaloricDishNames.forEach(System.out::println);
  threeHighCaloricDishNames.forEach(System.out::println);

/*
java.util.stream.SliceOps$1@6acbcfc0
java.util.stream.SliceOps$1@6acbcfc0
pork
beef
chicken
Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:229)
    at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
    at Main.main(Main.java:34)
*/

λ‚΄λΆ€ 반볡과 μ™ΈλΆ€ 반볡

  • μ™ΈλΆ€ 반볡
    • μ‚¬μš©μžκ°€ 직접 μš”μ†Œλ₯Ό λ°˜λ³΅ν•˜λŠ” 것 (μ»¬λ ‰μ…˜ μΈν„°νŽ˜μ΄μŠ€ for-eachλ“±)
    • μ»¬λ ‰μ…˜ λ‚΄λΆ€μ μœΌλ‘œ 숨겨쑌던 반볡자λ₯Ό μ‚¬μš©ν•˜λŠ” 것
    • 즉 , λͺ…μ‹œμ μœΌλ‘œ μ»¬λ ‰μ…˜ ν•­λͺ©μ„ ν•˜λ‚˜μ”© κ°€μ Έμ™€μ„œ μ²˜λ¦¬ν•œλ‹€.
    • 병렬성을 슀슀둜 κ΄€λ¦¬ν•΄μ•Όν•œλ‹€.
  List<String> names = new ArrayList<>();
  for(Dish dish : menu){
      names.add(dish.getName());
  }

  Iterator<Dish> iterator = menu.iterator();
  while(iterator.hasNext()){
      Dish dish = iterator.next();
      names.add(dish.getName());
  }
  • 슀트림 λΌμ΄λΈŒλŸ¬λ¦¬λŠ” λ‚΄λΆ€ λ°˜λ³΅μ„ μ‚¬μš©ν•œλ‹€.
    • λ°˜λ³΅μ„ μ•Œμ•„μ„œ μ²˜λ¦¬ν•˜κ³  κ²°κ³Ό 슀트림 값을 μ–΄λ”˜κ°€μ— μ €μž₯ν•΄μ£ΌλŠ” 것
    • ν•¨μˆ˜μ— μ–΄λ–€ μž‘μ—…μ„ μˆ˜ν–‰ν• μ§€λ§Œ μ§€μ •ν•˜λ©΄ λͺ¨λ“ κ²ƒμ΄ μ•Œμ•„μ„œ μ²˜λ¦¬λœλ‹€.
    • μž‘μ—…μ„ 투λͺ…ν•˜κ²Œ λ³‘λ ¬λ‘œ μ²˜λ¦¬ν•˜κ±°λ‚˜ , 더 μ΅œμ ν™”λœ λ‹€μ–‘ν•œ μˆœμ„œλ‘œ μ²˜λ¦¬ν•  수 μžˆλ‹€.
List<String> innerIterNames = menu.stream()
                                  .map(dish -> dish.getName())
                                  .collect(toList());


슀트림 μ—°μ‚°

  • java.util.stream.Stream μΈν„°νŽ˜μ΄μŠ€λŠ” λ§Žμ€ 연산을 μ •μ˜ν•œλ‹€.

쀑간 μ—°μ‚°

  • μ—°κ²°ν•  수 μžˆλŠ” 슀트림 μ—°μ‚°
  • filter λ‚˜ sorted 같은 쀑간 연산은 λ‹€λ₯Έ μŠ€νŠΈλ¦Όμ„ λ°˜ν™˜ν•œλ‹€.
  • πŸ“Œμ€‘κ°„ μ—°μ‚°μ˜ μ€‘μš”ν•œ νŠΉμ§•μ€ μ΅œμ’… 연산을 슀트림 νŒŒμ΄ν”„λΌμΈμ— μ‹€ν–‰ν•˜κΈ° μ „κΉŒμ§€λŠ” 아무 연산도 μˆ˜ν–‰ν•˜μ§€ μ•ŠλŠ”λ‹€λŠ” 것 ➜ lazy
    • 쀑간 연산을 ν•©μΉœ λ‹€μŒμ— 합쳐진 쀑간 연산을 μ΅œμ’… μ—°μ‚°μœΌλ‘œ ν•œ λ²ˆμ— μ²˜λ¦¬ν•˜κΈ° λ•Œλ¬Έμ΄λ‹€.
  List<String> threeHighCaloricDishNames =
          menu.stream()
              .filter(dish -> {
                  System.out.println("filtering : " + dish.getName());
                  return dish.getCalories() > 300;
              })
              .map(dish -> {
                  System.out.println("mapping : " + dish.getName());
                  return dish.getName();
              })
              .limit(3)
              .collect(toList());

  System.out.println(threeHighCaloricDishNames);
filtering : pork
mapping : pork
filtering : beef
mapping : beef
filtering : chicken
mapping : chicken
[pork, beef, chicken]

lazyν•œ νŠΉμ„± 덕뢄에 λͺ‡ κ°€μ§€ μ΅œμ ν™” 효과λ₯Ό 얻을 수 μžˆμ—ˆλ‹€.

  1. 300μΉΌλ‘œλ¦¬κ°€ λ„˜λŠ” μš”λ¦¬λŠ” μ—¬λŸ¬ κ°œμ§€λ§Œ 였직 처음 3개만 μ„ νƒλ˜μ—ˆλ‹€.
    • μ΄λŠ” limitμ—°μ‚° 그리고 μ‡ΌνŠΈ μ„œν‚·μ΄λΌ λΆˆλ¦¬λŠ” 기법 덕뢄이닀. (5μž₯μ—μ„œ μ„€λͺ…)
  2. filter와 map은 μ„œλ‘œ λ‹€λ₯Έ μ—°μ‚°μ΄μ§€λ§Œ 루프 퓨전을 μ‚¬μš©ν•˜μ—¬ ν•œ κ³Όμ •μœΌλ‘œ λ³‘ν•©λ˜μ—ˆλ‹€.
μ—°μ‚° λ°˜ν™˜ ν˜•μ‹ μ—°μ‚°μ˜ 인수 ν•¨μˆ˜ λ””μŠ€ν¬λ¦½ν„°
filter Stream<T> Predicate<T> T ➜ boolean
map Stream<T> Function<T , R> T ➜ R
limit Stream<T>
sorted Stream<T> Comparator<T> (T , T) ➜ int
distinct Stream<T>

μ΅œμ’… μ—°μ‚°

  • μŠ€νŠΈλ¦Όμ„ λ‹«λŠ” μ—°μ‚°
  • 슀트림 νŒŒμ΄ν”„λΌμΈμ—μ„œ κ²°κ³Όλ₯Ό λ„μΆœν•œλ‹€.
  • 보톡 μ΅œμ’… 연산에 μ˜ν•΄ List , Integer , void λ“± 슀트림 μ΄μ™Έμ˜ κ²°κ³Όκ°€ λ°˜ν™˜λœλ‹€.
μ—°μ‚° λ°˜ν™˜ ν˜•μ‹ λͺ©μ 
forEach void 슀트림의 각 μš”μ†Œλ₯Ό μ†ŒλΉ„ν•˜λ©΄μ„œ λžŒλ‹€λ₯Ό μ μš©ν•œλ‹€.
count long 슀트림의 μš”μ†Œκ°œμˆ˜λ₯Ό λ°˜ν™˜ν•œλ‹€.
collect μŠ€νŠΈλ¦Όμ„ λ¦¬λ“€μŠ€ν•΄μ„œ 리슀트 , λ§΅ , μ •μˆ˜ ν˜•μ‹μ˜ μ»¬λ ‰μ…˜μ„ λ§Œλ“ λ‹€. 6μž₯ μ°Έμ‘°

ν€΄μ¦ˆ

  • λ‹€μŒ 슀트림 νŒŒμ΄ν”„λΌμΈμ—μ„œ 쀑간 μ—°μ‚°κ³Ό μ΅œμ’… 연산을 κ΅¬λ³„ν•˜μ‹œμ˜€.
long count = menu.stream()
                  .filter(d -> d.getCalories() > 300)
                  .distinct()
                  .limit(3)
                  .count();
  • countλŠ” 슀트림이 μ•„λ‹Œ long을 λ°˜ν™˜ν•œλ‹€.
  • λ”°λΌμ„œ countλŠ” μ΅œμ’… 연산이닀.
  • filter , distinct , limit은 μŠ€νŠΈλ¦Όμ„ λ°˜ν™˜ν•˜λ©° μ„œλ‘œ μ—°κ²°ν•  수 μžˆμœΌλ‹ˆ , 쀑간 연산이닀.

슀트림 μ΄μš©ν•˜κΈ°

  • 슀트림 이용 과정은 λ‹€μŒκ³Ό 같이 μ„Έκ°€μ§€λ‘œ μš”μ•½ν•  수 μžˆλ‹€.
  1. 질의λ₯Ό μˆ˜ν–‰ν•  (μ»¬λ ‰μ…˜ 같은) 데이터 μ†ŒμŠ€
  2. 슀트림 νŒŒμ΄ν”„λΌμΈμ„ ꡬ성할 쀑간 μ—°μ‚° μ—°κ²°
  3. 슀트림 νŒŒμ΄ν”„λΌμΈμ„ μ‹€ν–‰ν•˜κ³  κ²°κ³Όλ₯Ό λ§Œλ“€ μ΅œμ’… μ—°μ‚°
  • 슀트림 νŒŒμ΄ν”„λΌμΈμ˜ κ°œλ…μ€ λΉŒλ” νŒ¨ν„΄κ³Ό λΉ„μŠ·ν•˜λ‹€.
    • λΉŒλ” νŒ¨ν„΄μ—μ„œλŠ” ν˜ΈμΆœμ„ μ—°κ²°ν•΄μ„œ 섀정을 λ§Œλ“ λ‹€.
      • μŠ€νŠΈλ¦Όμ—μ„œ 쀑간 연산을 μ—°κ²°ν•˜λŠ” 것과 κ°™λ‹€.
    • 그리고 μ€€λΉ„λœ 섀정에 buildλ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•œλ‹€
      • μŠ€νŠΈλ¦Όμ—μ„œ μ΅œμ’… μ—°μ‚°κ³Ό κ°™λ‹€.

πŸ“Œλ§ˆμΉ˜λ©°

  • μŠ€νŠΈλ¦Όμ€ μ†ŒμŠ€μ—μ„œ μΆ”μΆœλœ 연속 μš”μ†Œλ‘œ , 데이터 처리 연산을 μ§€μ›ν•œλ‹€.
  • μŠ€νŠΈλ¦Όμ€ λ‚΄λΆ€ λ°˜λ³΅μ„ μ§€μ›ν•œλ‹€.
  • μŠ€νŠΈλ¦Όμ—λŠ” 쀑간 μ—°μ‚°κ³Ό μ΅œμ’… 연산이 μžˆλ‹€.
  • 쀑간 연산은 stream을 λ°˜ν™˜ν•˜λŠ” 것이며 , 쀑간 μ—°μ‚°μœΌλ‘œλŠ” μ–΄λ–€ 결과도 생성할 수 μ—†λ‹€.
  • μ΅œμ’… 연산은 forEachλ‚˜ count처럼 stream을 λ°˜ν™˜ν•˜μ§€ μ•ŠλŠ” 것이닀.
  • 슀트림의 μš”μ†ŒλŠ” μš”μ²­ν•  λ•Œ lazyν•˜κ²Œ κ³„μ‚°λœλ‹€.
⚠️ **GitHub.com Fallback** ⚠️