java - 如何将嵌套对象列表缩减为 Map

标签 java for-loop collections java-8 java-stream

我有这个问题需要使用 Java 8 流来解决,但到目前为止我还没有成功。

我有:

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

所有对象都有自己的 equals 实现,因此可以比较对象。

这是我必须迭代的数据:

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

我想知道哪个客户给了公司更多的钱。

我已经使用这样的 foreach 解决了这个问题:

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

但我想知道一种用流解决这个问题的方法。

我的第一个想法是改变这个 一个 Map,其中 BigDecimal 值将是所有客户购买的总和。

有什么建议吗?

谢谢。

最佳答案

让我们一步一步来。

  1. 如何获取订单行的价格?
BigDecimal getPrice(OrderLine orderLine) {
    return orderLine.getProduct()
                    .getPrice()
                    .multiply(BigDecimal.valueOf(orderLine.getQuantity()));
}
  1. 如何获得订单的总价?
BigDecimal getPrice(Order order) {
    return order.getOrderLines()
                .stream()
                .map(orderLine -> getPrice(orderLine))
                .collect(reducing(BigDecimal.ZERO, BigDecimal::add));
}
  1. 现在假设您已经实现了上述方法,您如何确定每位客户花费的总金额?
Map<Customer, BigDecimal> totalPerCustomer =
    orders.stream()
          .collect(groupingBy(Order::getCustomer,
                              reducing(BigDecimal.ZERO, o -> getPrice(o), BigDecimal::add)));
  1. 既然您已将所有信息存储在方便的 map 中,那么您如何确定哪个客户花了最多的钱?
Optional<Customer> topCustomer = 
    totalPerCustomer.entrySet()
                    .stream()
                    .max(Map.Entry.comparingByValue())
                    .map(Map.Entry::getKey);

请注意,如果订单列表为空,topCustomer 将等于 Optional.empty()

关于java - 如何将嵌套对象列表缩减为 Map,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66544780/

相关文章:

Java列表可视化

java - 从 Java 对象更新/合并 SQLite 数据库表

Java 8集合: filter with function don't work

c - 在 C 中,如何循环每个没有连续值的枚举文字

r - 如何替换数组中的值?

java - 什么是乱操作、不安全操作?

java - 如何使用 System.out 作为 java 方法中的参数

java - 如何使用ListIterator?

java - RightCurlyBraceDifferentLineAsNextBlockCheck 已报告,但未处于 Activity 状态

c++ - 密码破解码合程序