作者:张逸紫惟雨 | 来源:互联网 | 2023-02-01 12:20
我有一系列发票:
class Invoice {
int month;
BigDecimal amount
}
我想合并这些发票,因此我每月收到一张发票,金额是本月发票金额的总和.
例如:
invoice 1 : {month:1,amount:1000}
invoice 2 : {month:1,amount:300}
invoice 3 : {month:2,amount:2000}
输出:
invoice 1 : {month:1,amount:1300}
invoice 2 : {month:2,amount:2000}
我怎么能用java 8流做到这一点?
编辑:因为我的Invoice类是可变的,修改它们不是问题,我选择了Eugene的解决方案
Collection invoices = list.collect(Collectors.toMap(Invoice::getMonth, Function.identity(), (left, right) -> {
left.setAmount(left.getAmount().add(right.getAmount()));
return left;
})).values();
Eugene..
21
如果你可以返回Collection
它,它将如下所示:
Collection invoices = list.collect(Collectors.toMap(Invoice::getMonth, Function.identity(), (left, right) -> {
left.setAmount(left.getAmount().add(right.getAmount()));
return left;
})).values();
如果你真的需要List
:
list.stream().collect(Collectors.collectingAndThen(Collectors.toMap(Invoice::getMonth, Function.identity(), (left, right) -> {
left.setAmount(left.getAmount().add(right.getAmount()));
return left;
}), m -> new ArrayList<>(m.values())));
两者都明显假设Invoice
是可变的......
1> Eugene..:
如果你可以返回Collection
它,它将如下所示:
Collection invoices = list.collect(Collectors.toMap(Invoice::getMonth, Function.identity(), (left, right) -> {
left.setAmount(left.getAmount().add(right.getAmount()));
return left;
})).values();
如果你真的需要List
:
list.stream().collect(Collectors.collectingAndThen(Collectors.toMap(Invoice::getMonth, Function.identity(), (left, right) -> {
left.setAmount(left.getAmount().add(right.getAmount()));
return left;
}), m -> new ArrayList<>(m.values())));
两者都明显假设Invoice
是可变的......
嗨!2评论... 1)也许它应该是`list.stream().collect(...)`和2)你正在改变原来的`Invoice`元素,这对我来说看起来不正确......你可以通过添加复制构造函数并在值映射器中使用它来解决它
2> Federico Per..:
如果您可以将以下复制构造函数和合并方法添加到您的Invoice
类:
public Invoice(Invoice another) {
this.mOnth= another.month;
this.amount = another.amount;
}
public Invoice merge(Invoice another) {
amount = amount.add(another.amount); // BigDecimal is immutable
return this;
}
您可以根据需要减少,如下所示:
Collection result = list.stream()
.collect(Collectors.toMap(
Invoice::getMonth, // use month as key
Invoice::new, // use copy cOnstructor=> don't mutate original invoices
Invoice::merge)) // merge invoices with same month
.values();
我正在使用Collectors.toMap
这个工作,它有三个参数:一个将流的元素映射到键的函数,一个将流的元素映射到值的函数和一个用于在发生碰撞时组合值的合并函数按键.