The classes that I have the following domain classes:
@AllArgsConstructor
@Getter
@ToString
public static class Customer {
private String id;
private String name;
}
@Getter
public static class Order {
private String id;
private Set<OrderContent> orderContent = new HashSet<>();
private Customer customer;
public Order(String id, Customer customer) {
this.id = id;
this.customer = customer;
}
public Order addOrderContent(Product product, int amount) {
orderContent.add(new OrderContent(product, amount));
return this;
}
}
@AllArgsConstructor
@Getter
public static class Product {
private String name;
private BigDecimal price;
}
@AllArgsConstructor
@Getter
public static class OrderContent {
private Product product;
private Integer quantity;
}
So each Order is associated with a Customer and one-to-many association with OrderContent. Each OrderContent has properties: product and quantity.
I would like to return the most valuable customer, which is the customer that has the highest value of all placed orders.
Let's consider the example below:
List<Order> orders = new ArrayList<>();
Customer customer1 = new Customer("1", "Bill");
Customer customer2 = new Customer("2", "John");
Product device1 = new Product("Device 1", new BigDecimal("30.00"));
Product device2 = new Product("Device 2", new BigDecimal("50.00"));
Product device3 = new Product("Device 3", new BigDecimal("110.00"));
orders.add(new Order("1", customer1).addOrderContent(device1 , 1));
orders.add(new Order("2", customer1).addOrderContent(device2 , 1));
orders.add(new Order("3", customer2).addOrderContent(device3, 1));
The code below fail to compile. The problem is located inside the collector, because the types of arguments inside mapping() does not match. How to implement this logic properly?
My code:
Customer customer = orders.stream()
.collect(Collectors.groupingBy(Order::getCustomer,
Collectors.mapping((Order order) -> order.getOrderContent().stream()
.map(orderContent -> orderContent.getProduct().getPrice()
.multiply(new BigDecimal(orderContent.getQuantity()))),
Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))
))
.entrySet().stream()
.max(Comparator.comparing(Map.Entry::getValue))
.map(Map.Entry::getKey).orElse(null);