λλ€λ₯Ό μ¬μ©ν΄μΌ λλ μ΄μ
λλ€μ μ€νΈλ¦Όμ κ°λ
λ€μ΄κ°κΈ° μμμ, λλ€μκ³Ό, λλ€νλ©΄ λΉΌλμ μ μλ μ€νΈλ¦Όμ κ°λ μ μ 리ν΄λ³΄μ.
λλ€μμ νλμ ννλ²μΌλ‘ μ΅λͺ ν¨μλ₯Ό κ°κ²°νκ² νννλ λ°©λ²μ΄λ€.
→ μλ° 8λΆν° λμ λ ν¨μν νλ‘κ·Έλλ°μ μ§μνκΈ° μν κΈ°λ₯μ΄λ€.
ννλ²μ λ€μκ³Ό κ°λ€.
(λ§€κ°λ³μ1, λ§€κ°λ³μ2, ...) -> { ꡬν }
μ€νΈλ¦Όμ΄λ λ§μ°¬κ°μ§λ‘ μλ° 8λΆν° λμ λ κΈ°λ₯μΌλ‘, 컬λ μ μ μ²λ¦¬νκ³ λ€μν μ°μ°μ μννλλ° μ¬μ©νλ APIμ΄λ€.
μ£Όλ‘ μ»¬λ μ μ μ μ₯λ μμλ₯Ό νλμ© μ°Έμ‘°νμ¬ λλ€μμΌλ‘ μ²λ¦¬ν μ μλ€.
κ·Έλ κΈ° λλ¬Έμ λλ€μ μ€νΈλ¦Όμ λ°μ ν κ΄κ³λ₯Ό κ°μ§κ³ μλ€.
μλμ 첨λΆν μ¬μ§μ 보면 μ΄ν΄κ° μ½λ€.
λ€μ μ¬μ§μ, μΌλ°μ μΌλ‘ 컬λ μ
μμλ₯Ό μ²λ¦¬ν λ μ¬μ©νλ for
λ¬Έμμ μ¬μ©νλ μΈλΆ λ°λ³΅μ, κ·Έλ¦¬κ³ Stream
μμ μ¬μ©νλ λ΄λΆ λ°λ³΅μμ΄λ€.

λ°λ³΅μ΄ μΈλΆμμ μΌμ΄λ¨ (forλ¬Έ)

λ°λ³΅μ΄ λ΄λΆμμ μΌμ΄λ¨ (Stream)
μ€νΈλ¦Όμ μ£Όμ κΈ°λ₯
- νν°λ§(
Filtering
): μ£Όμ΄μ§ 쑰건μ λ§λ μμλ₯Ό μ ν - λ§€ν(
Mapping
): μμλ₯Ό λ€λ₯Έ κ°μΌλ‘ λ³ννκ±°λ μΆμΆ - μ λ ¬(
Sorting
): μμλ₯Ό μ λ ¬ - 리λμ±(
Reducing
): μμλ€μ κ²°ν©νμ¬ λ¨μΌ κ²°κ³Όλ₯Ό λμΆ - μ§κ³(
Aggregating
): μμλ€μ κ·Έλ£Ήννκ±°λ ν΅κ³ μ 보λ₯Ό κ³μ°
μμΈν 건 μλμ λλ€μ μ€νΈλ¦Όμ μμ λ₯Ό ν΅ν΄μ μμ보λλ‘ νμ.
λλ€μ μ₯λ¨μ
κ·Έλ¬λ©΄, λλ€λ₯Ό μ μ¬μ©ν΄μΌλλμ§ λ λ¬΄μ¨ μ₯μ μ΄ μλμ§μ λν΄μ μμ보μ.
κ°λ°μλΌλ©΄ λꡬλ μ¬μ©νλ(?) 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) );
- λ¨μ μΆλ ₯
μμ μ½λλ κΈ°μ‘΄μ μ¬μ©νλ μΌλ°μ μΈ λ°λ³΅λ¬Έμ΄λ€.//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 - π‘ λλ€μμμμ λ©μλ μ°Έμ‘°λ λΆνμν λ§€κ°λ³μλ₯Ό μλ΅ νλ κ²μ΄λ€.
- κ·ΈλΌ, μ΄μ λλ€λ₯Ό μ΄μ©ν μμ λ₯Ό μ΄ν΄λ³΄μ.
- λ¨Όμ , μΌλ°μ μΈ μΆλ ₯λ°©μμ μμ λ‘ λ€μλ€. (
for
) 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);
}
- λ§μ§λ§μΌλ‘, 컬λ μ
μ μ€λ³΅ μ κ±°λ κ°λ₯νλ€.
distinct()
λ₯Ό μ¬μ©νλ©΄ μ€λ³΅ μ κ±°κ° κ°λ₯νλ€. //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);
}
- λ°λ©΄μ,
μ€νΈλ¦Ό_μνλͺ μ΄_μλμ°¨μΈκ²λ€λ§_νν°λ§()
λ₯Ό 보면 κΈ°μ‘΄μ 3μ€ μ΄μμ μ½λμμ 1μ€ μ§λ¦¬ μ½λλ‘ λ°λ κ²μ νμΈ ν μ μλ€. //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);
}
filter()
λreturn
κ°μ΄true
μΈκ²λ€λ§ μΆμΆνλ λ©μλμ΄λ€.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");
μλμ κ°μ΄, 컬λ μ μμμ κ°μ²΄ λ©μλ λΏλ§μλλΌ μ§μ λ©μλλ₯Ό λ§λ€μ΄ λ§€νλ κ°λ₯νλ€. (μ μ λ©μλλ κ°λ₯)}
//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; }
- μνλͺ λ§μ μΆμΆνλ κ°λ¨ν λλ€μ μμ λΆν° μκ°νκ² λ€.
map()
μ λ§κ·Έλλ‘ λ§€νμ νλ κΈ°λ₯μ΄λ©°, 컬λ μ μ μμκ°μ λ³κ²½νλ κ²μ΄λΌκ³ 보면λλ€.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κ°μ ν μ€νΈ μ½λλ λ€ λμΌν κΈ°λ₯μ νλ κ²μ΄λ€.μ΄κ²λ°λ‘ λλ€μ μλ ₯μ΄ μλκΉλΌλ μκ°μ΄λ λ€.}
- μμμ μλλ‘ μμ μ μ½λκ° λμ± κ°κ²°ν΄μ§λ κ²μ λλ μ μμ κ²μ΄λ€.
- ν μ€νΈμ λ©μλ λͺ μ²λΌ μνμ κ°κ²© μμΌλ‘ μ λ ¬ ν μ΅μκ°μ μΆμΆνλ μμ μ΄λ€.
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
λ¬Έμ μ¬λ¬λ² μ¨μΌλλ μ΄μκ°μμ§λ§,μ€νΈλ¦Ό_μν_μΉ΄ν κ³ λ¦¬_κ·Έλ£Ήν()
보면 μκ² μ§λ§, μ€νΈλ¦Ό APIμCollectors.groupingBy()
μ μ΄μ©νμ¬ νμ€λ‘ κ·Έλ£Ήνμ ν μ μλ€.//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<>()); } //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);
}
- μμ λ₯Ό μν΄ μν κ°μ²΄μ μΉ΄ν κ³ λ¦¬λ₯Ό μΆκ°νμλ€.
μμ μμ μ΄μΈμλ μ€νΈλ¦Ό APIκ° “μ€ μ΄κ±° κΉμ§ κ°λ₯ν΄?”λΌλ λ¬Όμνκ° λ° μ λλ‘ λ§μ κΈ°λ₯μ μ 곡νκ³ μλ€.
π‘ μΆμ²μ 곡μλ¬Έμλ₯Ό 보면 λ§μ μ€νΈλ¦Ό APIλ€μ΄ μλ€.
μλ°κ° κ³μ μ κ·Έλ μ΄λ λλ©΄μ ν¨μν μΈν°νμ΄μ€λ₯Ό λ§μ΄ μΆκ΅¬νκ³ κΆμ₯νκ³ μλ€.
κ·Έλμ, λλ€μ μ€νΈλ¦Όμ κΆμ₯μ΄ μλ νμκ° λκ³ μλ€.
κ·Έλ μ§λ§ λ λ¨μ©μ νλ©΄ μλκΈ° λλ¬Έμ μ νμ΅νκ³ νμ©νμΌλ©΄ μ’κ² λ€.
μμ μμ μμ€λ€μ κ°μΈ κΉνλΈμ μ λ‘λ νμμΌλ μ°Έκ³ λ°λλ€.
[μΆμ²]
https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html
https://steady-coding.tistory.com/598
[Github]
'π±Backend' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
νμ΄μ¬ FastAPIλ₯Ό μ΄μ©ν API νλ‘μ νΈ λ§λ€κΈ° (1) - μ€ν¬λν API λ§λ€κΈ° (0) | 2024.11.26 |
---|---|
νμ΄μ¬ FastAPIλ₯Ό μ΄μ©ν API νλ‘μ νΈ λ§λ€κΈ° (0) - μκ° λ° μμ (0) | 2024.11.26 |
νμ΄μ¬ μΉ μ€ν¬λν - λ©λ‘ μμ μΆμΆ (2) | 2024.03.29 |
SNS λ‘κ·ΈμΈ - Spring OAuth2 Client (0) | 2023.07.24 |
μ€νλ§ API λΉλκΈ° λ ΌλΈλ‘νΉ λ°©μ νΈμΆ (0) | 2023.03.27 |