按字段对对象列表进行分组并在其中一个字段中应用二进制函数以使用流 java 8 在一行代码中将其减少总和
Grouping list of object by a field & applying binary function in one of the field to reduce it by sum in one line of code using stream 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
是一个 Collector,其中 groupingBy
将放置每个组,您可以 "sum ints" 或任何您想要的.
比如分组数据不直接是整数,可以映射:
Map<String, Integer> paymentListByCodeAndAmount = payments.stream()
.collect(groupingBy(Payment::getPaymentCode,
mapping(p -> p.amount * p.txnId,
summingInt(x -> x))));
读作 “以支付为流,按支付代码分组,取金额和 txnId 的乘积并给我总和”。
但是,当然,存在数百万种组合,而不是简单地求和,您可以总结(最小值、最大值、平均值、...)并用这个做一些事情:
Map<String, Double> paymentListByCodeAndAmount = payments.stream()
.collect(groupingBy(Payment::getPaymentCode,
collectingAndThen(summarizingInt(p -> p.amount * p.txnId),
IntSummaryStatistics::getAverage)));
读作“以支付为流,按支付代码分组,总结金额和txnId的乘积,然后给我平均值”。
让我们举个例子,我有一个交易列表,其中包含 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
是一个 Collector,其中 groupingBy
将放置每个组,您可以 "sum ints" 或任何您想要的.
比如分组数据不直接是整数,可以映射:
Map<String, Integer> paymentListByCodeAndAmount = payments.stream()
.collect(groupingBy(Payment::getPaymentCode,
mapping(p -> p.amount * p.txnId,
summingInt(x -> x))));
读作 “以支付为流,按支付代码分组,取金额和 txnId 的乘积并给我总和”。
但是,当然,存在数百万种组合,而不是简单地求和,您可以总结(最小值、最大值、平均值、...)并用这个做一些事情:
Map<String, Double> paymentListByCodeAndAmount = payments.stream()
.collect(groupingBy(Payment::getPaymentCode,
collectingAndThen(summarizingInt(p -> p.amount * p.txnId),
IntSummaryStatistics::getAverage)));
读作“以支付为流,按支付代码分组,总结金额和txnId的乘积,然后给我平均值”。