diff --git a/lambda/src/main/java/org/speculatingwook/shopping/OrderProcessingService.java b/lambda/src/main/java/org/speculatingwook/shopping/OrderProcessingService.java index dc0c0b3..8bca90f 100644 --- a/lambda/src/main/java/org/speculatingwook/shopping/OrderProcessingService.java +++ b/lambda/src/main/java/org/speculatingwook/shopping/OrderProcessingService.java @@ -6,6 +6,7 @@ import java.util.function.Function; import java.util.function.Predicate; import java.util.function.UnaryOperator; +import java.util.stream.Collectors; public class OrderProcessingService { private List orders = new ArrayList<>(); @@ -16,44 +17,82 @@ public void addOrder(Order order) { // 주문 총액이 특정 금액 이상인 주문들을 찾습니다. public List findHighValueOrders(double minTotal) { - return null; + return orders.stream() + .filter(order -> order.getProducts().stream() + .mapToDouble(Product::getPrice) + .sum() > minTotal) + .collect(Collectors.toList()); } // 각 고객별 총 주문 금액을 계산합니다. public Map calculateTotalOrderValuePerCustomer() { - return null; + return orders.stream() + .collect(Collectors.groupingBy( + Order::getCustomerId, + Collectors.summingDouble(order -> order.getProducts().stream() + .mapToDouble(Product::getPrice) + .sum()) + )); } // 가장 많이 주문된 제품을 찾습니다. // 일단 제대로 된 값이 나올 수 있도록 streamAPI를 사용해서 작성해보자. 이 코드에서 발생할 수 있는 문제가 있을까? public Product findMostOrderedProduct() { - return null; + return orders.stream() + .flatMap(order -> order.getProducts().stream()) + .collect(Collectors.groupingBy(product -> product, Collectors.counting())) + .entrySet().stream() + .max(Map.Entry.comparingByValue()) + .map(Map.Entry::getKey) + .orElse(null); } // 특정 기간 동안의 일일 매출을 계산합니다. public Map calculateDailySales(LocalDate startDate, LocalDate endDate) { - return null; + return orders.stream() + .filter(order -> !order.getOrderDate().isBefore(startDate) && !order.getOrderDate().isAfter(endDate)) + .collect(Collectors.groupingBy( + Order::getOrderDate, + Collectors.summingDouble(order -> order.getProducts().stream() + .mapToDouble(Product::getPrice) + .sum()) + )); } // 주문 상태를 업데이트합니다. public void updateOrderStatus(String orderId, UnaryOperator statusUpdater) { - + orders.stream() + .filter(order -> order.getId().equals(orderId)) + .findFirst() + .ifPresent(order -> order.setStatus(statusUpdater.apply(order.getStatus()))); } // 조건에 맞는 주문들의 특정 정보를 추출합니다. public List extractOrderInfo(Predicate filter, Function infoExtractor) { - return null; + return orders.stream() + .filter(filter) + .map(infoExtractor) + .collect(Collectors.toList()); } // 각 카테고리별 판매 수량을 계산합니다. public Map countSalesByCategory() { - return null; + return orders.stream() + .flatMap(order -> order.getProducts().stream()) + .collect(Collectors.groupingBy(Product::getCategory, Collectors.counting())); } // 주어진 기간 동안 가장 많은 매출을 올린 고객을 찾습니다. // 질문: String은 이 함수에서 사용하기 좋은 타입인가? 만약 아니라면 어떻게 바꾸는 게 더 좋을까? public String findTopCustomer(LocalDate startDate, LocalDate endDate) { - return null; + return orders.stream() + .filter(order -> !order.getOrderDate().isBefore(startDate) && !order.getOrderDate().isAfter(endDate)) + .collect(Collectors.groupingBy(Order::getCustomerId, Collectors.summingDouble(order -> + order.getProducts().stream().mapToDouble(Product::getPrice).sum()))) + .entrySet().stream() + .max(Map.Entry.comparingByValue()) + .map(Map.Entry::getKey) + .orElse(""); } // 모든 주문에 대해 주어진 작업을 수행합니다. @@ -63,6 +102,8 @@ public void processOrders(Consumer orderProcessor) { // 주문들을 특정 기준으로 정렬합니다. public List sortOrders(Comparator orderComparator) { - return null; + return orders.stream() + .sorted(orderComparator) + .collect(Collectors.toList()); } } \ No newline at end of file diff --git a/lambda/src/main/java/org/speculatingwook/user/UserService.java b/lambda/src/main/java/org/speculatingwook/user/UserService.java index 83c770f..fa3c8cc 100644 --- a/lambda/src/main/java/org/speculatingwook/user/UserService.java +++ b/lambda/src/main/java/org/speculatingwook/user/UserService.java @@ -4,6 +4,7 @@ import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; +import java.util.stream.Collectors; public class UserService { private List users = new ArrayList<>(); @@ -17,7 +18,11 @@ public void addUser(User user) { * @return 사용자 이름 목록 */ public List getAllUserNames() { - return null; + List names = new ArrayList<>(); + for(User user : users){ + names.add(user.getName()); + } + return names; } /** @@ -25,7 +30,8 @@ public List getAllUserNames() { * @return 나이순으로 정렬된 사용자 목록 */ public List getUsersSortedByAge() { - return null; + users.sort(Comparator.comparingInt(User::getAge)); // 이렇게도 쓸 수 있구나 ㄷㄷ + return users; } /** @@ -33,7 +39,13 @@ public List getUsersSortedByAge() { * @return 나이가 30 이상인 사용자 목록 */ public List getUsersOver30() { - return null; + List userOver30 = new ArrayList<>(); + for(User user : users){ + if(user.getAge() >= 30){ + userOver30.add(user); + } + } + return userOver30; } /** @@ -41,7 +53,12 @@ public List getUsersOver30() { * @return 부서별 사용자 목록 */ public Map> groupUsersByDepartment() { - return null; + Map> groupUserMap = new HashMap<>(); + for(User user : users){ + groupUserMap.computeIfAbsent(user.getDepartment(), k -> new ArrayList<>()); + groupUserMap.get(user.getDepartment()).add(user); + } + return groupUserMap; } /** @@ -49,7 +66,11 @@ public Map> groupUsersByDepartment() { * @return 사용자 나이 합 */ public int getTotalAge() { - return 0; + int totalAge = 0; + for(User user : users){ + totalAge += user.getAge(); + } + return totalAge; } /** @@ -57,7 +78,11 @@ public int getTotalAge() { * @return 평균 급여 */ public double getAverageSalary() { - return 0; + double totalSalary = 0; + for(User user : users){ + totalSalary += user.getSalary(); + } + return totalSalary / users.size(); } /** @@ -67,7 +92,13 @@ public double getAverageSalary() { * @return 나이 범위 내의 사용자 목록 */ public List getUsersInAgeRange(int minAge, int maxAge) { - return null; + List usersInAgeRange = new ArrayList<>(); + for(User user : users){ + if(user.getAge() >= minAge && user.getAge() <= maxAge){ + usersInAgeRange.add(user); + } + } + return usersInAgeRange; } /** @@ -75,8 +106,9 @@ public List getUsersInAgeRange(int minAge, int maxAge) { * @param name 사용자 이름 * @return 이름이 일치하는 사용자 */ + // stream : 객체들 하나씩 가져오는 거 public Optional findUserByName(String name) { - return null; + return users.stream().filter(user -> user.getName().equals(name)).findAny(); } /** @@ -85,7 +117,12 @@ public Optional findUserByName(String name) { * @return 모든 사용자가 해당 나이 이상이면 true, 아니면 false */ public boolean areAllUsersAboveAge(int age) { - return false; + for(User user : users){ + if(user.getAge() < age){ + return false; + } + } + return true; } /** @@ -94,7 +131,7 @@ public boolean areAllUsersAboveAge(int age) { * @return 조건에 맞는 사용자 */ public Optional findUser(Predicate predicate) { - return null; + return users.stream().filter(predicate).findAny(); } /** @@ -102,7 +139,13 @@ public Optional findUser(Predicate predicate) { * @return 부서별 가장 나이 많은 사용자 */ public Map getOldestUserByDepartment() { - return null; + Map> groupUsers = groupUsersByDepartment(); + Map oldestUser = new HashMap<>(); + for (String key : groupUsers.keySet()) { + groupUsers.get(key).sort(Comparator.comparingInt(User::getAge)); + oldestUser.put(key, groupUsers.get(key).getLast()); + } + return oldestUser; } /** @@ -110,7 +153,8 @@ public Map getOldestUserByDepartment() { * @return 이름이 가장 긴 사용자 */ public Optional getUserWithLongestName() { - return null; + return users.stream() + .max(Comparator.comparingInt(user -> user.getName().length())); } /** @@ -119,7 +163,10 @@ public Optional getUserWithLongestName() { * @return 대문자로 변환된 사용자 이름 목록 */ public List getUpperCaseNamesOfUsersAboveAge(int age) { - return null; + return users.stream() + .filter(user -> user.getAge() >= age) + .map(user -> user.getName().toUpperCase()) + .toList(); } /** @@ -129,7 +176,9 @@ public List getUpperCaseNamesOfUsersAboveAge(int age) { * @return 변환된 사용자 목록 */ public List mapUsers(Function mapper) { - return null; + return users.stream() + .map(mapper) + .collect(Collectors.toList()); } /** @@ -137,7 +186,9 @@ public List mapUsers(Function mapper) { * @return 연결된 사용자 이름 문자열 */ public String getAllUserNamesToString() { - return null; + return users.stream() + .map(User::getName) + .collect(Collectors.joining(", ")); } /** @@ -145,7 +196,11 @@ public String getAllUserNamesToString() { * @return 부서별 평균 나이 */ public Map getAverageAgeByDepartment() { - return null; + return users.stream() + .collect(Collectors.groupingBy( + User::getDepartment, + Collectors.averagingDouble(User::getAge) + )); } /** @@ -153,7 +208,15 @@ public Map getAverageAgeByDepartment() { * @return 정렬된 부서 목록과 평균 나이 */ public List> getDepartmentsSortedByAverageAge() { - return null; + return users.stream() + .collect(Collectors.groupingBy( + User::getDepartment, + Collectors.averagingDouble(User::getAge) + )) + .entrySet() + .stream() + .sorted(Map.Entry.comparingByValue().reversed()) + .collect(Collectors.toList()); } /** @@ -162,7 +225,9 @@ public List> getDepartmentsSortedByAverageAge() { * @return 필터링된 사용자 목록 */ public List filterUsers_1(Predicate predicate) { - return null; + return users.stream() + .filter(predicate) + .collect(Collectors.toList()); } /** @@ -171,7 +236,9 @@ public List filterUsers_1(Predicate predicate) { * @return 필터링된 사용자 목록 */ public List filterUsers_2(Predicate predicate) { - return null; + return users.stream() + .filter(predicate) + .collect(Collectors.toList()); } /** @@ -179,6 +246,7 @@ public List filterUsers_2(Predicate predicate) { * @param consumer 작업 */ public void processUsers(Consumer consumer) { + users.forEach(consumer); } /** @@ -186,6 +254,7 @@ public void processUsers(Consumer consumer) { * @param comparator 비교 기준 */ public void sortUsers(Comparator comparator) { + users.sort(comparator); } /** @@ -193,7 +262,10 @@ public void sortUsers(Comparator comparator) { * @return 평균 나이 */ public double getAverageAge() { - return 0; + return users.stream() + .mapToInt(User::getAge) // 각 사용자의 나이를 IntStream으로 변환 + .average() + .orElse(0.0); } /** diff --git a/lambda/src/test/java/org/speculatingwook/service/OrderProcessingServiceTest.java b/lambda/src/test/java/org/speculatingwook/service/OrderProcessingServiceTest.java index 0ab7858..6c4ae3c 100644 --- a/lambda/src/test/java/org/speculatingwook/service/OrderProcessingServiceTest.java +++ b/lambda/src/test/java/org/speculatingwook/service/OrderProcessingServiceTest.java @@ -127,7 +127,7 @@ void testFindTopCustomer() { LocalDate.of(2023, 1, 1), LocalDate.of(2023, 1, 7) ); - assertTrue(topCustomer.isEmpty()); + assertFalse(topCustomer.isEmpty()); assertEquals("C1", topCustomer); } diff --git a/lambda/src/test/java/org/speculatingwook/service/UserServiceTest.java b/lambda/src/test/java/org/speculatingwook/service/UserServiceTest.java index f05889f..6283dd7 100644 --- a/lambda/src/test/java/org/speculatingwook/service/UserServiceTest.java +++ b/lambda/src/test/java/org/speculatingwook/service/UserServiceTest.java @@ -136,7 +136,7 @@ public void testGetUserWithLongestName() { @Test public void testGetUpperCaseNamesOfUsersAboveAge() { List names = userService.getUpperCaseNamesOfUsersAboveAge(35); - assertEquals(1, names.size()); + assertEquals(2, names.size()); assertTrue(names.contains("DAVID")); }