Java calculate max customer price using streams

  • A+
Category:Languages

I have a problem with streams. I have many Customer objects and I would like to calculate which one of them paid the most.

This is my sample data:

class Orders {      private List<Order> orders = new ArrayList<>();      public void prepareData() {          Product socks = new ProductBuilder()                 .setPrice(new BigDecimal("23"))                 .setCategory(Category.C)                 .setName("SOCKS")                 .build();          Product jacket = new ProductBuilder()                 .setPrice(new BigDecimal("199"))                 .setCategory(Category.A)                 .setName("JACKET")                 .build();          Product watch = new ProductBuilder()                 .setPrice(new BigDecimal("100"))                 .setCategory(Category.B)                 .setName("WATCH CASIO")                 .build();           Customer john = new CustomerBuilder()                 .setAge(18)                 .setName("JOHN")                 .setSurname("JOHNSON")                 .setEmail("john@johnson.com")                 .build();          Customer mike = new CustomerBuilder()                 .setAge(20)                 .setName("MIKE")                 .setSurname("MAX")                 .setEmail("mike@max.com")                 .build();           Order orderJohn = new OrderBuilder()                 .setQuantity(2)                 .setCustomer(john)                 .setProduct(watch)                 .setOrderDate(LocalDate.now())                 .build();          Order orderJohn2 = new OrderBuilder()                 .setQuantity(4)                 .setCustomer(john)                 .setProduct(socks)                 .setOrderDate(LocalDate.now())                 .build();            Order orderMike = new OrderBuilder()                 .setQuantity(2)                 .setCustomer(mike)                 .setProduct(jacket)                 .setOrderDate(LocalDate.now())                 .build();          orders.add(orderJohn);         orders.add(orderJohn2);         orders.add(orderMike);     } } 

Now I should group by customer because one customer has many orders and calculate price * and quantity and select maximum using orders.stream()? How can I do that?

My class definitions:

public class Order {      private Customer customer;     private Product product;     private int quantity;     private LocalDate orderDate;    //get/set } public class Customer {      private String name;     private String surname;     private int age;     private String email;     //get/set } public class Product {     private String name;     private BigDecimal price;     private Category category;     //get/set } 

And builders

    public class CustomerBuilder {          private Customer customer = new Customer();          public CustomerBuilder setName(String name){             customer.setName(name);             return this;         }          public CustomerBuilder setSurname(String surname){             customer.setSurname(surname);             return this;         }          public CustomerBuilder setAge(int age){             customer.setAge(age);             return this;         }          public CustomerBuilder setEmail(String email){             customer.setEmail(email);             return this;         }          public Customer build()  {              return customer;         }      } public class OrderBuilder {    private Order order = new Order();     public OrderBuilder setCustomer(Customer customer){        order.setCustomer(customer);        return this;    }     public OrderBuilder setProduct(Product product){        order.setProduct(product);        return this;    }     public OrderBuilder setQuantity(int quantity){        order.setQuantity(quantity);        return this;    }     public OrderBuilder setOrderDate(LocalDate orderDate){        order.setOrderDate(orderDate);        return this;    }     public Order build(){        return order;    }  } public class ProductBuilder {      private Product product = new Product();      public ProductBuilder setCategory(Category category){         product.setCategory(category);         return this;     }      public ProductBuilder setName(String name){         product.setName(name);         return this;     }      public ProductBuilder setPrice(BigDecimal bigDecimal){         product.setPrice(bigDecimal);         return this;     }      public Product build() {         return product;     } } 

 


The following finds the top customer by first grouping by the customer field (mapped to the total of corresponding purchase value [quantity * price]).

The result of that aggregation is then traversed to find "max" by total purchase value.

Customer topCustomer = orders.stream()         .collect(Collectors.groupingBy(Order::getCustomer,                 Collectors.mapping(                         order -> order.getProduct()                                       .getPrice()                                       .multiply(new BigDecimal(order.getQuantity())),                         Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))))         .entrySet().stream()         .max(Comparator.comparing(Entry::getValue))         .map(Entry::getKey)         .orElse(null); 

It's important to note that this assumes hashCode() and equals() are properly overridden in Customer for the grouping to work correctly.

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: