My current attempt is based on double type class members:
public Client whoPaidTheMost() {
/*METHOD EXPLOITING STREAM API*/
return shopping.entrySet()
.stream()
.collect(Collectors.groupingBy(Map.Entry::getKey,
Collectors.flatMapping(e -> e.getValue().entrySet().stream(),
Collectors.summingDouble(e->e.getKey().getPrize() * e.getValue())))) /*should be refactored*/
.entrySet().stream()
.max(Comparator.comparingDouble(Map.Entry::getValue))/*should be refactored*/
.get()
.getKey();
}
shopping is basically a map: Map<Client, Map<Product,Integer>>
,
- The outer Key represents the Client
- The inner Key represents the Product
- the inner maps value (Integer) reprents the number of specified product which belong to a specific client
Product class members are name, category, price (previously of double type) - want to refactor the provided code into one using price as a type of BigDecimal
How could I make this code work also for BigDecimals - ?
Basically I' ve refactored that arleady:
Client client = shopping.entrySet()
.stream()
.collect(Collectors.groupingBy(Map.Entry::getKey,
Collectors.flatMapping(e -> e.getValue().entrySet().stream(),
Collectors.mapping(e -> BigDecimal.valueOf(new Long(e.getValue())).multiply(e.getKey().getPrize()),
Collectors.reducing(BigDecimal.ZERO, BigDecimal::add)))))
.entrySet().stream()
.max((e1, e2) -> (e1.getValue().compareTo(e2.getValue())))
.get()
.getKey();
Still wondering if it's possible to refactor this without using: Collectors.mapping(e -> BigDecimal.valueOf(new Long(e.getValue())).multiply(e.getKey().getPrize())
before Collectors.reducing
?
You can refactor it like this,
shopping.entrySet().stream()
.collect(
Collectors.groupingBy(Map.Entry::getKey,
Collectors.flatMapping(
e -> e.getValue().entrySet().stream()
.map(innerEntry -> innerEntry.getKey().getPrice()
.multiply(BigDecimal.valueOf(innerEntry.getValue()))),
Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))))
.entrySet().stream()
.max(Map.Entry.comparingByValue()).get().getKey();
You don't need any additional mapping
Collector
here. Merely use the map
operator to convert your Map.Entry
into a BigDecimal
based on your computation, and pass that Stream<BigDecimal>
down. The final reduction operator does the trick here. Zero acts as a good identity element for this sum.