如何从List<>获得总和和最低日期与lambda

时间:2018-05-24 15:05:19

标签: java lambda

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 

        });
    }

2 个答案:

答案 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();

我不担心“优化”这个并尝试在一个循环中执行它,除非这可能是您系统中的一个主要瓶颈(不太可能)。保持两个想法分开使代码更容易理解和维护。

您使用BigDecimal

执行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);