public class BusinessLog {
private Date logDate;
private double prize;
}
给定对象BusinessLog,我需要为List<BusinessLog> list
中的所有奖项求和,还需要从列表中返回最低日期,是否可以使用lambda,
我可以肯定地使用forEach,但是如何使用lambda,
到目前为止,我试图做的是,
BigDecimal balance = BigDecimal.ZERO;
if (list != null) {
list.forEach(businessLog -> {
balance.add(BigDecimal.valueOf(businessLog.getPrize()));
// how to get lowest date
});
}
答案 0 :(得分:1)
要计算多个自定义聚合,您应该编写自定义缩减器。
例如,以下reducer计算一个BusinessLog
对象中的统计信息。以下假设要声明构造函数public BusinessLog(double prize, Date logDate)
。
BusinessLog stats =
bl.stream()
.reduce((log1, log2) -> new BusinessLog(
log1.getPrize() + log2.getPrize(),
log1.getLogDate().before(log2.getLogDate()) ?
log1.getLogDate() : log2.getLogDate()
)).get();
Date lowestDate = stats.getLogDate();
double prizeSum = stats.getPrize();
请注意,使用BusinessLog
作为临时统计信息持有人本质上是一种黑客行为。你需要为此目的设计一个单独的类。
答案 1 :(得分:1)
要查找最短日期,您可以执行以下操作:
Optional<Date> minDate = list.stream().map(v -> v.logDate).min(Date::compareTo);
计算总和:
double sum = list.stream().mapToDouble(v -> v.prize).sum();
我不担心“优化”这个并尝试在一个循环中执行它,除非这可能是您系统中的一个主要瓶颈(不太可能)。保持两个想法分开使代码更容易理解和维护。
执行balance.add(...)
到BigDecimal
的代码实际上不会按照您编写它的方式工作,因为add
上的BigDecimal
方法返回了一个新实例而不是改变现有的实例。 BigDecimal
个实例是不可变的。您无法为balance
分配新值,因为它有效final
来自lambda的上下文。
使用BigDecimal
的想法虽然很好。对于精确小数位重要的任何事情(例如金钱),您应该避免使用double
。如果您将prize
更改为BigDecimal,则无法使用sum()
,但您可以使用reduce()
来完成相同的功能。
BigDecimal sum = list.stream().map(v -> v.prize).reduce(BigDecimal.ZERO, BigDecimal::add);