Java使用流计算最大客户价格

时间:2018-10-08 12:30:45

标签: java java-8 java-stream

我对流有问题。我有许多Intent对象,我想计算其中哪个对象支付的费用最高。

这是我的示例数据:

Customer

现在我应该按客户分组,因为一个客户有很多订单并计算价格*和数量,并使用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); } } 选择最大值?我该怎么办?

我的班级定义:

orders.stream()

和建设者

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
}

2 个答案:

答案 0 :(得分:10)

以下内容通过首先按customer字段分组(映射到相应购买价值[quantity * price的总数)来找到主要客户。

然后遍历该聚合的结果,以按购买总值找到“最大值”。

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);

请务必注意,这假设hashCode()中的equals()Customer已正确覆盖,以便分组正常工作。

编辑:

如果还需要购买总额,则需要获取完整的条目,而不是仅映射到键(以下代码基于以上代码段):

Optional<Entry<Customer, BigDecimal>> topCustomerEntry = 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));

BigDecimal topValue = null; //total value for top customer
Customer customer = null;   //customer with most purchases

if(topCustomerEntry.isPresent()) {
    topValue = topCustomerEntry.get().getValue();
    customer = topCustomerEntry.get().getKey();
}

这将只打印值。但是您可以重组代码以将其分配给变量。

答案 1 :(得分:2)

如果您需要花费最多的客户(例如通过电子邮件):

  orders.stream()
            .collect(Collectors.toMap(
                    x -> x.getCustomer().getEmail(),
                    x -> x.getProduct().getPrice().multiply(new BigDecimal(x.getQuantity())),
                    BigDecimal::add))
            .entrySet()
            .stream()
            .max(Entry.comparingByValue())
            .ifPresent(System.out::println);