Java流有条件地添加多个值

我有一个像这样的对象列表,其中数量可以是负数或正数:

class Sale {
   String country;
   BigDecimal amount;
}

我想最终得到一对所有负值和所有正值的总和,按国家/地区分类。

使用这些值:

country | amount
nl      | 9
nl      | -3
be      | 7.9
be      | -7

有没有办法最终Map<String, Pair<BigDecimal, BigDecimal>>使用单个流?

使用两个单独的流很容易做到这一点,但我无法仅用一个流来解决。

回答

它应该Collectors.toMap与合并函数一起使用来对对求和。

假设 aPair是不可变的,并且只有第一个和第二个元素的 getter,代码可能如下所示:

static Map<String, Pair<BigDecimal, BigDecimal>> sumUp(List<Sale> list) {
    return list.stream()
               .collect(Collectors.toMap(
                   Sale::getCountry,
                   sale -> sale.getAmount().signum() >= 0 
                       ? new Pair<>(sale.getAmount(), BigDecimal.ZERO)
                       : new Pair<>(BigDecimal.ZERO, sale.getAmount()),
                   (pair1, pair2) -> new Pair<>(
                       pair1.getFirst().add(pair2.getFirst()),
                       pair1.getSecond().add(pair2.getSecond())
                   )
                   // , LinkedHashMap::new // optional parameter to keep insertion order
               ));
}

测试

List<Sale> list = Arrays.asList(
    new Sale("us", new BigDecimal(100)),
    new Sale("uk", new BigDecimal(-10)),
    new Sale("us", new BigDecimal(-50)),
    new Sale("us", new BigDecimal(200)),
    new Sale("uk", new BigDecimal(333)),
    new Sale("uk", new BigDecimal(-70))
);

Map<String, Pair<BigDecimal, BigDecimal>> map = sumUp(list);

map.forEach((country, pair) -> 
    System.out.printf("%-4s|%s%n%-4s|%s%n", 
        country, pair.getFirst(), country, pair.getSecond()
));

输出

uk  |333
uk  |-80
us  |300
us  |-50


以上是Java流有条件地添加多个值的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>