λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
🌱Backend

λžŒλ‹€λ₯Ό μ‚¬μš©ν•΄μ•Ό λ˜λŠ” 이유

by discphy 2023. 6. 5.
λ°˜μ‘ν˜•

λžŒλ‹€λ₯Ό μ‚¬μš©ν•΄μ•Ό λ˜λŠ” 이유

λžŒλ‹€μ™€ 슀트림의 κ°œλ…


λ“€μ–΄κ°€κΈ° μ•žμ„œμ„œ, λžŒλ‹€μ‹κ³Ό, λžŒλ‹€ν•˜λ©΄ 빼놓을 수 μ—†λŠ” 슀트림의 κ°œλ…μ„ μ •λ¦¬ν•΄λ³΄μž.

λžŒλ‹€μ‹μ€ ν•˜λ‚˜μ˜ ν‘œν˜„λ²•μœΌλ‘œ 읡λͺ… ν•¨μˆ˜λ₯Ό κ°„κ²°ν•˜κ²Œ ν‘œν˜„ν•˜λŠ” 방법이닀.

→ μžλ°” 8λΆ€ν„° λ„μž…λœ ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ°μ„ μ§€μ›ν•˜κΈ° μœ„ν•œ κΈ°λŠ₯이닀.

ν‘œν˜„λ²•μ€ λ‹€μŒκ³Ό κ°™λ‹€.

(λ§€κ°œλ³€μˆ˜1, λ§€κ°œλ³€μˆ˜2, ...) -> { κ΅¬ν˜„ }

μŠ€νŠΈλ¦Όμ΄λž€ λ§ˆμ°¬κ°€μ§€λ‘œ μžλ°” 8λΆ€ν„° λ„μž…λœ κΈ°λŠ₯으둜, μ»¬λ ‰μ…˜μ„ μ²˜λ¦¬ν•˜κ³  λ‹€μ–‘ν•œ 연산을 μˆ˜ν–‰ν•˜λŠ”λ° μ‚¬μš©ν•˜λŠ” API이닀.

주둜 μ»¬λ ‰μ…˜μ˜ μ €μž₯된 μš”μ†Œλ₯Ό ν•˜λ‚˜μ”© μ°Έμ‘°ν•˜μ—¬ λžŒλ‹€μ‹μœΌλ‘œ μ²˜λ¦¬ν•  수 μžˆλ‹€.

κ·Έλ ‡κΈ° λ•Œλ¬Έμ— λžŒλ‹€μ™€ μŠ€νŠΈλ¦Όμ€ λ°€μ ‘ν•œ 관계λ₯Ό κ°€μ§€κ³  μžˆλ‹€.

μ•„λž˜μ˜ μ²¨λΆ€ν•œ 사진을 보면 이해가 쉽닀.

λ‹€μŒ 사진은, 일반적으둜 μ»¬λ ‰μ…˜ μš”μ†Œλ₯Ό μ²˜λ¦¬ν• λ•Œ μ‚¬μš©ν•˜λŠ” forλ¬Έμ—μ„œ μ‚¬μš©ν•˜λŠ” μ™ΈλΆ€ 반볡자, 그리고 Streamμ—μ„œ μ‚¬μš©ν•˜λŠ” λ‚΄λΆ€ λ°˜λ³΅μžμ΄λ‹€.

반볡이 μ™ΈλΆ€μ—μ„œ 일어남

반볡이 μ™ΈλΆ€μ—μ„œ 일어남 (forλ¬Έ)

반볡이 λ‚΄λΆ€μ—μ„œ 일어남

반볡이 λ‚΄λΆ€μ—μ„œ 일어남 (Stream)

슀트림의 μ£Όμš” κΈ°λŠ₯


  • 필터링(Filtering): μ£Όμ–΄μ§„ 쑰건에 λ§žλŠ” μš”μ†Œλ₯Ό 선택
  • λ§€ν•‘(Mapping): μš”μ†Œλ₯Ό λ‹€λ₯Έ κ°’μœΌλ‘œ λ³€ν™˜ν•˜κ±°λ‚˜ μΆ”μΆœ
  • μ •λ ¬(Sorting): μš”μ†Œλ₯Ό μ •λ ¬
  • 리듀싱(Reducing): μš”μ†Œλ“€μ„ κ²°ν•©ν•˜μ—¬ 단일 κ²°κ³Όλ₯Ό λ„μΆœ
  • 집계(Aggregating): μš”μ†Œλ“€μ„ κ·Έλ£Ήν™”ν•˜κ±°λ‚˜ 톡계 정보λ₯Ό 계산

μžμ„Έν•œ 건 μ•„λž˜μ˜ λžŒλ‹€μ™€ 슀트림의 예제λ₯Ό ν†΅ν•΄μ„œ μ•Œμ•„λ³΄λ„λ‘ ν•˜μž.

λžŒλ‹€μ˜ μž₯단점


그러면, λžŒλ‹€λ₯Ό μ™œ μ‚¬μš©ν•΄μ•Όλ˜λŠ”μ§€ 또 무슨 μž₯점이 μžˆλŠ”μ§€μ— λŒ€ν•΄μ„œ μ•Œμ•„λ³΄μž.

개발자라면 λˆ„κ΅¬λ‚˜ μ‚¬μš©ν•˜λŠ”(?) ChatGPTμ—κ²Œ λ¬Όμ–΄λ³΄μ•˜λ‹€.

“μžλ°” λžŒλ‹€μ˜ μž₯점”이라고 ChatGPTμ—κ²Œ λ¬Όμ–΄λ³Έ λ‹΅μ•ˆμ΄λ‹€.

“μžλ°” λžŒλ‹€μ˜ μž₯점”이라고 ChatGPTμ—κ²Œ λ¬Όμ–΄λ³Έ λ‹΅μ•ˆμ΄λ‹€.

μ •λ¦¬ν•˜μžλ©΄,

  • κ°„κ²°ν•˜κ³  읽기 μ‰¬μš΄ μ½”λ“œ
  • ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ° 지원
  • μ½”λ“œμ˜ μž¬μ‚¬μš©μ„±
  • 닀쀑 μŠ€λ ˆλ“œ ν™˜κ²½μ—μ„œμ˜ ν™œμš©μ„±
  • μ»¬λ ‰μ…˜ 처리의 μš©μ΄μ„±

λ“±λ“± μ—¬λŸ¬κ°€μ§€ μž₯점듀 λ•Œλ¬Έμ— 주둜 μ‚¬μš©ν•œλ‹€.

μœ„μ˜ μž₯점 μ€‘μ—μ„œλ„ ν•„μžλŠ” 특히 μ½”λ“œμ˜ κ°„κ²°μ„±, 가독성 λ•Œλ¬Έμ— 주둜 μ‚¬μš©ν•œλ‹€.

λ°˜λ©΄μ—, λžŒλ‹€μ˜ 단점을 μ•Œμ•„λ³΄μž.

“μžλ°” λžŒλ‹€μ˜ 단점”이라고 ChatGPTμ—κ²Œ λ¬Όμ–΄λ³Έ λ‹΅μ•ˆμ΄λ‹€.

“μžλ°” λžŒλ‹€μ˜ 단점”이라고 ChatGPTμ—κ²Œ λ¬Όμ–΄λ³Έ λ‹΅μ•ˆμ΄λ‹€.

  • κ°€λ…μ„±μ˜ μ €ν•˜
  • λ””λ²„κΉ…μ˜ 어렀움
  • μ œν•œλœ κΈ°λŠ₯
  • λ©”λͺ¨λ¦¬ μ‚¬μš©λŸ‰ 증가
  • μ„±λŠ₯ μ˜€λ²„ν—€λ“œ

ν•„μžκ°€ λŠλΌκΈ°μ—λŠ” μœ„μ˜ 단점 μ€‘μ—μ„œ μ œν•œλœ κΈ°λŠ₯, λ””λ²„κΉ…μ˜ 어렀움이 κ°€μž₯ 큰 단점이라고 μƒκ°ν•œλ‹€.

ν•˜μ§€λ§Œ, 이 단점이 κ°œλ°œν•˜λŠ”λ° μžˆμ–΄ 치λͺ…적이진 μ•Šλ‹€κ³  μƒκ°ν•œλ‹€.

⚠️ μ œν•œλœ κΈ°λŠ₯ : 병렬 ν”„λ‘œκ·Έλž˜λ° 방식이라 멀버 λ³€μˆ˜μ˜ μž¬μ‚¬μš©μ΄ λΆˆκ°€λŠ₯ ν•˜λ‹€λŠ” 단점

예λ₯Ό λ“€λ©΄, μ»¬λ ‰μ…˜μ˜ λ‚΄λΆ€ λ°˜λ³΅μžμ— μ˜ν•΄μ„œ 싀행이 되기 λ•Œλ¬Έμ— λ©€λ²„λ³€μˆ˜μ˜ μž¬μ‚¬μš©μ΄ λΆˆκ°€λŠ₯ν•˜λ‹€. (final둜 μ •μ λ³€μˆ˜λ‘œλŠ” μ‚¬μš©μ΄ κ°€λŠ₯)

λžŒλ‹€μ™€ 슀트림 예제


이 글을 λ³΄λŠ” λ…μžλŠ” λŒ€λΆ€λΆ„μ΄ 개발자일 것 κ°™μ•„ μ½”λ“œλ₯Ό λ³΄λŠ”κ²Œ 더 이해가 λΉ λ₯Όκ±°λΌκ³ (?) μƒκ°λ˜μ–΄ 예제λ₯Ό 톡해 μ„€λͺ…ν•˜κ³ μž ν•œλ‹€.

슀트림 API 쀑 κ°€μž₯ 많이 μ‚¬μš©ν•˜λŠ” κΈ°λŠ₯을 예제둜 μž‘μ„±ν•˜μ˜€λ‹€. (μ˜ˆμ œλŠ” JUnit5λ₯Ό μ΄μš©ν•œ ν…ŒμŠ€νŠΈ μ½”λ“œλ‘œ μž‘μ„±ν•˜μ˜€λ‹€. )

μ˜ˆμ‹œμ— ν•„μš”ν•œ μƒν’ˆ(Item)μ΄λΌλŠ” 객체λ₯Ό λ§Œλ“€μ—ˆλ‹€.

//Item.java  @Data @AllArgsConstructor public class Item {      private Long id; // 아이디     private String itemName; // μƒν’ˆλͺ…     private Integer price; // μƒν’ˆκ°€κ²©     private Integer quantity; // μƒν’ˆμˆ˜λŸ‰ }

ν…ŒμŠ€νŠΈμ— ν•„μš”ν•œ 데이터λ₯Ό μ „μ—­ λ³€μˆ˜λ‘œ 선언을 ν•˜κ³  예제λ₯Ό μž‘μ„±ν•˜κ² λ‹€.

static List<Item> items = Arrays.asList(       new Item(1L, "μ±…A", 10000, 10),       new Item(2L, "μ±…B", 20000, 20),       new Item(3L, "μžλ™μ°¨A", 1000000, 3),       new Item(4L, "μžλ™μ°¨B", 2000000, 5),       new Item(5L, "μŒμ‹A", 8000, 150),       new Item(6L, "μŒμ‹B", 9000, 200),       new Item(7L, "μŒμ‹C", 10000, 300),       new Item(8L, "λ…ΈνŠΈλΆA", 100000, 20),       new Item(9L, "λ…ΈνŠΈλΆB", 40000, 40) );
  1. λ‹¨μˆœ 좜λ ₯
    //ItemPrintServiceTest.java  @Test void 일반_μ•„μ΄ν…œ_좜λ ₯_V_1() {     for (int i = 0; i < items.size(); i++) {         System.out.println("item = " + items.get(i));     } }  @Test void 일반_μ•„μ΄ν…œ_좜λ ₯_V_2() {     for (Item item : items) {         System.out.println("item = " + item);     } }
    μœ„μ˜ μ½”λ“œλŠ” 기쑴에 μ‚¬μš©ν–ˆλ˜ 일반적인 λ°˜λ³΅λ¬Έμ΄λ‹€.
    //ItemPrintServiceTest.java  @Test void λžŒλ‹€_μ•„μ΄ν…œ_좜λ ₯_V_1() {     items.forEach(item -> System.out.println("item = " + item)); }  @Test void λžŒλ‹€_μ•„μ΄ν…œ_좜λ ₯_μ°Έμ‘°_V_2() {     items.forEach(this::print); // λ©”μ„œλ“œ μ°Έμ‘° : λ§€κ°œλ³€μˆ˜κ°€ 동일할 λ•Œ μ‚¬μš©κ°€λŠ₯ν•˜λ‹€.  }  void print(Item item) {     System.out.println("item = " + item); }
    λžŒλ‹€λ₯Ό μ‚¬μš©ν•œ 예제 쀑 λžŒλ‹€_μ•„μ΄ν…œ_좜λ ₯_μ°Έμ‘°_V_2 λ₯Ό 보면 일반적인 μ½”λ“œλ³΄λ‹€ 훨씬 더 κ°„κ²°ν•΄μ§„ 것을 확인할 수 μžˆλ‹€.[μ°Έκ³ ] https://inpa.tistory.com/entry/JAVA8-β˜•-λžŒλ‹€μ‹μ„-더-짧게-λ©”μ†Œλ“œ-μ°Έμ‘°Method-Reference
  2. πŸ’‘ λžŒλ‹€μ‹μ—μ„œμ˜ λ©”μ†Œλ“œ μ°Έμ‘°λŠ” λΆˆν•„μš”ν•œ λ§€κ°œλ³€μˆ˜λ₯Ό μƒλž΅ ν•˜λŠ” 것이닀.
  3. 그럼, 이제 λžŒλ‹€λ₯Ό μ΄μš©ν•œ 예제λ₯Ό μ‚΄νŽ΄λ³΄μž.
  4. λ¨Όμ €, 일반적인 좜λ ₯방식을 예제둜 λ“€μ—ˆλ‹€. (for)
  5. filter() - ν•„ν„°μ•„λž˜λŠ”, 슀트림 API의 filter() λ©”μ†Œλ“œ κΈ°λŠ₯을 ν…ŒμŠ€νŠΈ μ½”λ“œλ‘œ μž‘μ„±ν•˜μ˜€λ‹€.for_μƒν’ˆλͺ…이_μžλ™μ°¨μΈκ²ƒλ“€λ§Œ_필터링() λ₯Ό 보면 forλ¬Έμ•ˆμ— if문이 또 λ“€μ–΄κ°€ μ½”λ“œκ°€ λ‹€μ†Œ λ³΅μž‘ν•΄ 보일 수 μžˆλ‹€. filter()λ₯Ό μ—¬λŸ¬ 번 μ‚¬μš©ν•œ μ˜ˆμ œμ΄λ‹€.μœ„μ™€κ°™μ΄ filter()λ₯Ό ν•œλ²ˆ 뿐이 μ•„λ‹Œ μ—¬λŸ¬ 번 μ‚¬μš©μ΄ κ°€λŠ₯ν•˜λ‹€.
    //ItemFilterServiceTest.java  @Test void μƒν’ˆκ°€κ²©_필터링_쀑볡_제거() {     //when     List<Integer> prices = items.stream()             .map(Item::getPrice) // λ’€μ—μ„œ μ„€λͺ…ν•  map() λ©”μ†Œλ“œμ΄λ©° μ°Έμ‘°λ₯Ό μ΄μš©ν•˜μ˜€λ‹€.             .distinct()             .collect(toList());
    //then assertThat(prices).hasSize(8); // 10000원 쀑볡 제거 9 - 1 = 8 assertThat(prices).containsExactly(10000, 20000, 1000000, 2000000, 8000, 9000, 100000, 40000);
    }
  6. λ§ˆμ§€λ§‰μœΌλ‘œ, μ»¬λ ‰μ…˜μ˜ 쀑볡 μ œκ±°λ„ κ°€λŠ₯ν•˜λ‹€. distinct()λ₯Ό μ‚¬μš©ν•˜λ©΄ 쀑볡 μ œκ±°κ°€ κ°€λŠ₯ν•˜λ‹€.
  7. //ItemFilterServiceTest.java @Test void μƒν’ˆλͺ…이_μŒμ‹μ΄λ©΄μ„œ_가격이_8500원_μ΄μƒμΈκ²ƒλ“€λ§Œ_필터링() { //when List<Item> foods = items.stream() .filter(item -> item.getItemName().contains("μŒμ‹")) .filter(item -> item.getPrice() > 8500) .collect(toList()); /* * μ•„λž˜μ™€ 같이 μ‚¬μš©ν•΄λ„ λœλ‹€. * .filter(item -> item.getItemName().contains("μŒμ‹") && item.getPrice() > 8500)) */
    //then assertThat(foods).hasSize(2);
    }
  8. λ°˜λ©΄μ—, 슀트림_μƒν’ˆλͺ…이_μžλ™μ°¨μΈκ²ƒλ“€λ§Œ_필터링()λ₯Ό 보면 기쑴의 3쀄 μ΄μƒμ˜ μ½”λ“œμ—μ„œ 1쀄 짜리 μ½”λ“œλ‘œ 바뀐 것을 확인 ν•  수 μžˆλ‹€.
  9. //ItemFilterServiceTest.java @Test void for_μƒν’ˆλͺ…이_μžλ™μ°¨μΈκ²ƒλ“€λ§Œ_필터링() { //given List<Item> cars = new ArrayList<>();
        //when for (Item item : items) {     if (item.getItemName().contains("μžλ™μ°¨")) {                     cars.add(item);             } }  //then assertThat(cars).hasSize(2);
    } @Test void 슀트림_μƒν’ˆλͺ…이_μžλ™μ°¨μΈκ²ƒλ“€λ§Œ_필터링() { //when List<Item> cars = items.stream().filter(item -> item.getItemName().contains("μžλ™μ°¨")).collect(toList());
    //then assertThat(cars).hasSize(2);
    }
  10. filter()λŠ” return값이 trueμΈκ²ƒλ“€λ§Œ μΆ”μΆœν•˜λŠ” λ©”μ†Œλ“œμ΄λ‹€.
  11. map() - λ§€ν•‘μ‹€μ œλ‘œ κ°€μž₯ 많이 μ‚¬μš©ν•˜λŠ” 슀트림 API이닀.
    //ItemMappingServiceTest.java  @Test void λžŒλ‹€_μƒν’ˆλͺ…λ§Œ_λ‚˜μ—΄() {         //when     List<String> itemNames = items.stream()             .map(Item::getItemName)             .collect(Collectors.toList());
    //then assertThat(itemNames).containsExactly("μ±…A",         "μ±…B",         "μžλ™μ°¨A",         "μžλ™μ°¨B",         "μŒμ‹A",         "μŒμ‹B",         "μŒμ‹C",         "λ…ΈνŠΈλΆA",         "λ…ΈνŠΈλΆB");
    }
    μ•„λž˜μ™€ 같이, μ»¬λ ‰μ…˜ μš”μ†Œμ˜ 객체 λ©”μ†Œλ“œ λΏλ§Œμ•„λ‹ˆλΌ 직접 λ©”μ†Œλ“œλ₯Ό λ§Œλ“€μ–΄ 맀핑도 κ°€λŠ₯ν•˜λ‹€. (정적 λ©”μ†Œλ“œλ„ κ°€λŠ₯)
  12. //ItemMappingServiceTest.java @Test void for_μƒν’ˆλͺ…이_책인_μƒν’ˆμ„_μˆ˜λŸ‰μ„_0개둜() { //given List<Item> books = new ArrayList<>();
    //when for (Item item : items) {     if (item.getItemName().contains("μ±…")) {         books.add(soldOutItem(item));     } }  //then assertThat(books).hasSize(2); assertThat(books).extracting("quantity").containsOnly(0);
    } @Test void λžŒλ‹€_μƒν’ˆλͺ…이_책인_μƒν’ˆμ„_μˆ˜λŸ‰μ„_0개둜() { //when List<Item> books = items.stream() .filter(item -> item.getItemName().contains("μ±…")) .map(this::soldOutItem) .collect(Collectors.toList());
        //then assertThat(books).hasSize(2); assertThat(books).extracting("quantity").containsOnly(0);
    } private Item soldOutItem(Item item) { item.setQuantity(0); return item; }
  13. μƒν’ˆλͺ…λ§Œμ„ μΆ”μΆœν•˜λŠ” κ°„λ‹¨ν•œ λžŒλ‹€μ˜ μ˜ˆμ œλΆ€ν„° μ†Œκ°œν•˜κ² λ‹€.
  14. map()은 λ§κ·ΈλŒ€λ‘œ 맀핑을 ν•˜λŠ” κΈ°λŠ₯이며, μ»¬λ ‰μ…˜μ˜ μš”μ†Œκ°’μ„ λ³€κ²½ν•˜λŠ” 것이라고 λ³΄λ©΄λœλ‹€.
  15. sorted() - μ •λ ¬
    //ItemSortServiceTest.java  @Test void μ •λ ¬_μƒν’ˆκ°€κ²©μˆœ_μ •λ ¬_ν›„_μ΅œμ†Ÿκ°’_V_1() {         //given     items.sort(new Comparator<Item>() {         @Override         public int compare(Item o1, Item o2) {             return o1.getPrice().compareTo(o2.getPrice());         }     });
    //when Item firstItem = items.get(0); System.out.println("firstItem = " + firstItem);  //then assertThat(firstItem.getId()).isEqualTo(5L); assertThat(firstItem.getItemName()).isEqualTo("μŒμ‹A"); assertThat(firstItem.getPrice()).isEqualTo(8000);
    } @Test void μ •λ ¬_μƒν’ˆκ°€κ²©μˆœ_μ •λ ¬_ν›„_μ΅œμ†Ÿκ°’_V_2() { //given items.sort((o1, o2) -> o1.getPrice().compareTo(o2.getPrice()));
    //when Item firstItem = items.get(0); System.out.println("firstItem = " + firstItem);  //then assertThat(firstItem.getId()).isEqualTo(5L); assertThat(firstItem.getItemName()).isEqualTo("μŒμ‹A"); assertThat(firstItem.getPrice()).isEqualTo(8000);
    } @Test void μ •λ ¬_μƒν’ˆκ°€κ²©μˆœ_μ •λ ¬_ν›„_μ΅œμ†Ÿκ°’_V_3() { //given items.sort(Comparator.comparing(Item::getPrice));
    //when Item firstItem = items.get(0); System.out.println("firstItem = " + firstItem);  //then assertThat(firstItem.getId()).isEqualTo(5L); assertThat(firstItem.getItemName()).isEqualTo("μŒμ‹A"); assertThat(firstItem.getPrice()).isEqualTo(8000);
    } @Test void 슀트림_μ •λ ¬_μƒν’ˆκ°€κ²©μˆœ_μ •λ ¬_ν›„_μ΅œμ†Ÿκ°’() { //when Item firstItem = items.stream().min(Comparator.comparing(Item::getPrice)).get(); System.out.println("firstItem = " + firstItem);
    //then assertThat(firstItem.getId()).isEqualTo(5L); assertThat(firstItem.getItemName()).isEqualTo("μŒμ‹A"); assertThat(firstItem.getPrice()).isEqualTo(8000);
    }
    4개의 ν…ŒμŠ€νŠΈ μ½”λ“œλŠ” λ‹€ λ™μΌν•œ κΈ°λŠ₯을 ν•˜λŠ” 것이닀.μ΄κ²Œλ°”λ‘œ λžŒλ‹€μ˜ μœ„λ ₯이 μ•„λ‹κΉŒλΌλŠ” 생각이든닀.
  16. μœ„μ—μ„œ μ•„λž˜λ‘œ 예제의 μ½”λ“œκ°€ λ”μš± κ°„κ²°ν•΄μ§€λŠ” 것을 λŠλ‚„ 수 μžˆμ„ 것이닀.
  17. ν…ŒμŠ€νŠΈμ˜ λ©”μ†Œλ“œ λͺ…μ²˜λŸΌ μƒν’ˆμ„ 가격 순으둜 μ •λ ¬ ν›„ μ΅œμ†Ÿκ°’μ„ μΆ”μΆœν•˜λŠ” μ˜ˆμ œμ΄λ‹€.
  18. collect() - 집계
    //ItemCategory.java  @Data @AllArgsConstructor public class ItemCategory {
    private Long id; private String itemName; private Category category; private Integer price; private Integer quantity;
    }
    //Category.java  public enum Category {     BOOK, CAR, FOOD, LAPTOP }
    μ΄λ²ˆμ—λŠ”, μƒν’ˆμ„ μΉ΄ν…Œκ³ λ¦¬ λ³„λ‘œ 그룹을 λ§Œλ“€μ–΄λ³΄λŠ” μ˜ˆμ œμ΄λ‹€.μΉ΄ν…Œκ³ λ¦¬ λ³„λ‘œ 그룹을 μ§“κΈ° μœ„ν•΄μ„  for문을 μ—¬λŸ¬λ²ˆ μ¨μ•Όλ˜λŠ” μ΄μŠˆκ°€μžˆμ§€λ§Œ,
  19. 슀트림_μƒν’ˆ_μΉ΄ν…Œκ³ λ¦¬_κ·Έλ£Ήν•‘()보면 μ•Œκ² μ§€λ§Œ, 슀트림 API와 Collectors.groupingBy()을 μ΄μš©ν•˜μ—¬ ν•œμ€„λ‘œ 그룹핑을 ν•  수 μžˆλ‹€.
  20. //ItemAggregationServiceTest.java static List<ItemCategory> items = Arrays.asList( new ItemCategory(1L, "μ±…A", BOOK, 10000, 10), new ItemCategory(2L, "μ±…B", BOOK, 20000, 20), new ItemCategory(3L, "μžλ™μ°¨A", CAR, 1000000, 3), new ItemCategory(4L, "μžλ™μ°¨B", CAR, 2000000, 5), new ItemCategory(5L, "μŒμ‹A", FOOD, 8000, 150), new ItemCategory(6L, "μŒμ‹B", FOOD, 9000, 200), new ItemCategory(7L, "μŒμ‹C", FOOD, 10000, 300), new ItemCategory(8L, "λ…ΈνŠΈλΆA", LAPTOP, 100000, 20), new ItemCategory(9L, "λ…ΈνŠΈλΆB", LAPTOP, 40000, 40) ); @Test void 일반_μƒν’ˆ_μΉ΄ν…Œκ³ λ¦¬_κ·Έλ£Ήν•‘() { //given Map<Category, List<ItemCategory>> itemGroups = new HashMap<>();
    for (Category category : Category.values()) {     itemGroups.put(category, new ArrayList&lt;&gt;()); }  //when for (ItemCategory item : items) {     itemGroups.get(item.getCategory()).add(item); }  //then assertThat(itemGroups.keySet()).contains(BOOK, CAR, FOOD, LAPTOP); assertThat(itemGroups.get(BOOK).size()).isEqualTo(2); assertThat(itemGroups.get(CAR).size()).isEqualTo(2); assertThat(itemGroups.get(FOOD).size()).isEqualTo(3); assertThat(itemGroups.get(BOOK).size()).isEqualTo(2);
    } @Test void 슀트림_μƒν’ˆ_μΉ΄ν…Œκ³ λ¦¬_κ·Έλ£Ήν•‘() { //when Map<Category, List<ItemCategory>> itemGroups = items.stream().collect(groupingBy(ItemCategory::getCategory));
    //then assertThat(itemGroups.keySet()).contains(BOOK, CAR, FOOD, LAPTOP); assertThat(itemGroups.get(BOOK).size()).isEqualTo(2); assertThat(itemGroups.get(CAR).size()).isEqualTo(2); assertThat(itemGroups.get(FOOD).size()).isEqualTo(3); assertThat(itemGroups.get(BOOK).size()).isEqualTo(2);
    }
  21. 예제λ₯Ό μœ„ν•΄ μƒν’ˆ 객체에 μΉ΄ν…Œκ³ λ¦¬λ₯Ό μΆ”κ°€ν•˜μ˜€λ‹€.

μœ„μ˜ 예제 이외에도 슀트림 APIκ°€ “였 이거 κΉŒμ§€ κ°€λŠ₯ν•΄?”λΌλŠ” λ¬ΌμŒν‘œκ°€ 뜰 μ •λ„λ‘œ λ§Žμ€ κΈ°λŠ₯을 μ œκ³΅ν•˜κ³  μžˆλ‹€.

πŸ’‘ 좜처의 κ³΅μ‹λ¬Έμ„œλ₯Ό 보면 λ§Žμ€ 슀트림 API듀이 μžˆλ‹€.

μžλ°”κ°€ 계속 μ—…κ·Έλ ˆμ΄λ“œ λ˜λ©΄μ„œ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λ₯Ό 많이 μΆ”κ΅¬ν•˜κ³  ꢌμž₯ν•˜κ³ μžˆλ‹€.

κ·Έλž˜μ„œ, λžŒλ‹€μ™€ μŠ€νŠΈλ¦Όμ€ ꢌμž₯이 μ•„λ‹Œ ν•„μˆ˜κ°€ λ˜κ³ μžˆλ‹€.

κ·Έλ ‡μ§€λ§Œ 또 λ‚¨μš©μ€ ν•˜λ©΄ μ•ˆλ˜κΈ° λ•Œλ¬Έμ— 잘 ν•™μŠ΅ν•˜κ³  ν™œμš©ν–ˆμœΌλ©΄ μ’‹κ² λ‹€.

μœ„μ˜ 예제 μ†ŒμŠ€λ“€μ€ 개인 κΉƒν—ˆλΈŒμ— μ—…λ‘œλ“œ ν•˜μ˜€μœΌλ‹ˆ μ°Έκ³  λ°”λž€λ‹€.

[좜처]

https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html

https://steady-coding.tistory.com/598

[Github]

https://github.com/discphy/stream-example

λ°˜μ‘ν˜•