java - 按字段对对象列表进行分组并在其中一个字段中应用二进制函数以使用流 java 8 在一行代码中按总和减少它
问题描述
举个例子,我有一个交易列表,其中包含 txnId、paymentCode、金额。输出应该是每个付款代码明智地收集了多少金额。
我尝试根据付款代码作为键和付款代码的金额列表对其进行分组,但我无法减少它。
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
class Payment {
Integer txnId;
String paymentCode;
Integer amount;
Payment(Integer txnId, String paymentCode, Integer amount) {
this.txnId = txnId;
this.paymentCode = paymentCode;
this.amount = amount;
}
public String getPaymentCode() {
return this.paymentCode;
}
public Integer getAmount() {
return this.amount;
}
@Override
public String toString() {
return "Payment [txnId=" + txnId + ", paymentCode=" + paymentCode + ", amount=" + amount + "]";
}
}
public class ListGroupingSum {
public static void main(String[] args) {
List<Payment> payments = new ArrayList<>();
payments.add(new Payment(100, "GPAY", 100));
payments.add(new Payment(101, "CC", 200));
payments.add(new Payment(102, "PAYTM", 300));
payments.add(new Payment(103, "GPAY", 400));
payments.add(new Payment(104, "CC", 500));
// @formatter:off
Map<String, List<Integer>> paymentListByCodeAndAmount = payments.stream()
.collect(Collectors.groupingBy(Payment::getPaymentCode, Collectors.mapping(Payment::getAmount, Collectors.toList())));
System.out.println(paymentListByCodeAndAmount);
//System.out.println(paymentListByCodeAndAmount.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)));
// @formatter:on
}
}
这给出了输出
{CC=[200, 500], GPAY=[100, 400], PAYTM=[300]}
但是,期望是
{CC=700, GPAY=500, PAYTM=300}
解决方案
Map<String, Integer> paymentListByCodeAndAmount = payments.stream()
.collect(groupingBy(Payment::getPaymentCode, summingInt(Payment::getAmount)));
(完全符合您的预期输出)
真的,summingInt
是一个收集器,groupingBy
将放置每个组,您可以“汇总整数”或任何您想要的。
例如,如果组数据不是直接整数,则可以映射:
Map<String, Integer> paymentListByCodeAndAmount = payments.stream()
.collect(groupingBy(Payment::getPaymentCode,
mapping(p -> p.amount * p.txnId,
summingInt(x -> x))));
读作“将付款作为流,按付款代码分组,取金额和 txnId 的乘积,然后给我总和”。
但是,当然,存在数以百万计的组合,而不是简单地总结你可以总结 (min, max, avg, ...) 并用这个做一些事情:
Map<String, Double> paymentListByCodeAndAmount = payments.stream()
.collect(groupingBy(Payment::getPaymentCode,
collectingAndThen(summarizingInt(p -> p.amount * p.txnId),
IntSummaryStatistics::getAverage)));
读作“将付款作为流,按付款代码分组,汇总金额和 txnId 的乘积,然后给我平均值”。
推荐阅读
- java - 无法关闭 Java 确认子窗口 (Vaadin 8)
- batch-file - 创建批处理文件以使用参数运行 cmd
- java - Apache Commons Compress:ZipArchiveEntry.getUnixMode() 始终返回 0
- c# - 如何检查输入是int还是string
- reactjs - Redux:基于可切换变量设置表单项的默认值
- python - 在这种情况下如何应用分页(Django Rest Framework)?
- python - 为什么 dropna() 会删除额外的行?
- algorithm - 从单词列表中查找使用我拥有的大多数字母的单词的算法
- go - Go中的Elasticsearch,Err:“客户端注意到服务器不是Elasticsearch,我们不支持这个未知产品”
- javascript - 从 RXJS observable 获取中间数据的最佳方式