I have this problem that I need to solve using Java 8 streams, but so far I have not succeeded.
I have:
public class Customer {
String id;
String firstName;
String lastName;
}
public class Order {
private final String id;
Set<OrderLine> orderLines = new HashSet<>();
Customer customer;
}
public class OrderLine {
Product product;
Integer quantity;
}
public class Product {
String name;
BigDecimal price;
}
All objects have their own equals implemented so its possible to compare objects.
This is the data that i have to iterate from:
List<Order> orders = new ArrayList<>();
Customer customer1 = new Customer(randomId(), "Will", "Sanders");
Customer customer2 = new Customer(randomId(), "Jonh", "Doe");
Product p1 = new Product("Book 1", new BigDecimal("50.00"));
Product p2 = new Product("Book 2", new BigDecimal("19.00"));
Product p3 = new Product("Book 3", new BigDecimal("100.00"));
orders.add(new Order(randomId(), customer1).addOrderLine(p1, 1));
orders.add(new Order(randomId(), customer1).addOrderLine(p2, 1));
orders.add(new Order(randomId(), customer2).addOrderLine(p3, 1));
And i want to know which customer has given more money to the company.
I have solved this using a foreach like this:
orders.forEach(order -> {
order.getOrderLines().forEach(orderLine -> {
if(!map.containsKey(order.getCustomer())) {
map.put(order.getCustomer(), orderLine.getProduct().getPrice());
} else {
map.put(order.getCustomer(),map.get(order.getCustomer()).add(orderLine.getProduct().getPrice()));
}
});
});
Customer c = Collections.max(map.entrySet(), Comparator.comparing(Map.Entry::getValue)).getKey();
but i would like to know a way to solve this with streams.
My first thought was transforming this a Map<Customer,BigDecimal>, where that BigDecimal value would be the sum of all customer purchases.
Any Sugestions?
Thanks.
1 Answer 1
Let's do it step by step.
- How can you get the price of an order line?
BigDecimal getPrice(OrderLine orderLine) {
return orderLine.getProduct()
.getPrice()
.multiply(BigDecimal.valueOf(orderLine.getQuantity()));
}
- How can you get the total price of an order?
BigDecimal getPrice(Order order) {
return order.getOrderLines()
.stream()
.map(orderLine -> getPrice(orderLine))
.collect(reducing(BigDecimal.ZERO, BigDecimal::add));
}
- Now assuming you have implemented the methods above, how can you determine the total money spent per each customer?
Map<Customer, BigDecimal> totalPerCustomer =
orders.stream()
.collect(groupingBy(Order::getCustomer,
reducing(BigDecimal.ZERO, o -> getPrice(o), BigDecimal::add)));
- Now as you have all the information stored in a convenient map, how can you determine which customer spent the most money?
Optional<Customer> topCustomer =
totalPerCustomer.entrySet()
.stream()
.max(Map.Entry.comparingByValue())
.map(Map.Entry::getKey);
Note that topCustomer
will be equal to Optional.empty()
if the list of orders is empty.
-
That's perfect, thanks for the explanation, i got it :Dcoder Tester– coder Tester2021年03月09日 20:21:17 +00:00Commented Mar 9, 2021 at 20:21
Explore related questions
See similar questions with these tags.