通过首先过滤同一对象的其他唯一值来求和对象的值

Pla*_*age 0 java list arraylist java-8 java-stream

假设我有一个对象列表,可称其为具有数量和价格作为字段的对象Order。

例如如下:

对象Order(字段quantityprice)列表包含以下值:

Quantity  Price

5         200
6         100
3         200
1         300
Run Code Online (Sandbox Code Playgroud)

现在,我想使用Java-8来获取以以下方式过滤的列表:

Quantity  Price

8         200
6         100
1         300
Run Code Online (Sandbox Code Playgroud)

价格是要过滤的唯一值,并对价格具有的任何数量进行求和,我想以此为基础形成一个新列表。

请建议我如何使用Java 8 Lambda表达式来完成此操作,谢谢。

Nik*_*las 9

以下Stream是窍门:

List<Order> o  = orders.stream().collect(
    Collectors.collectingAndThen(
        Collectors.groupingBy(Order::getPrice,Collectors.summingInt(Order::getQuantity)),
        map -> map.entrySet().stream()
                             .map(e -> new Order(e.getKey(), e.getValue()))
                             .collect(Collectors.toList())));
Run Code Online (Sandbox Code Playgroud)

让我们分解一下:

  1. 以下代码返回,Map<Integer, Integer>其中包含价格作为键(要作为总和的唯一值)及其总数量。键的方法是Collectors.groupingByclassifier描述键和downstream限定的值,这将是数量的总和,因此Collectors.summingInt(取决于该quantity类型):

    Map<Integer, Integer> map = orders.stream().collect(
        Collectors.groupingBy(                            // I want a Map<Integer, Integer>
            Order::getPrice,                              // price is the key
            Collectors.summingInt(Order::getQuantity))    // sum of quantities is the value
    
    Run Code Online (Sandbox Code Playgroud)
  2. 所需的结构是List<Order>,因此您要使用Collectors.collectingAndThen带有Collector<T, A, R> downstream和的方法Function<R, RR> finisher。的downstream是从所述第一点的分组,整理器将是一个转换Map<Integer, Integer>List<Order>

    List<Order> o  = orders.stream().collect(
    Collectors.collectingAndThen(
        grouping,                                                 // you know this one ;)
        map -> map.entrySet()                        
                  .stream()                                       // iterate entries
                  .map(e -> new Order(e.getKey(), e.getValue()))  // new Order(qty, price)
                  .collect(Collectors.toList())));                // as a List<Order>
    
    Run Code Online (Sandbox Code Playgroud)