使用Lambda表达式的一个对象中Java字段的总和

时间:2018-08-16 12:00:00

标签: java lambda java-8

我有这样的对象

class DailyReport{
LocalDate day;
Long criticalErrors;
Long browserErrors;
Long OtherErrors;
}

现在,我获得了此对象的列表,并想创建摘要对象,即

class Summary{
  LocalDate startDate;
LocalDate endDate;
Long sumOfCritical;
Long sumOfBrowser;
Long sumOfOthers
}

我这样创建了某事:

List<DailyReport> dailyReports=repository.findAll();
Summary summary = new Summary(
 dailyReports.get(0).getDay;
 dailyReports.get(dailyReports.size() - 1).getDay;
summary.stream().mapToLong(DailyReport::getCriticalErrors).sum(),
summary.stream().mapToLong(DailyReport::getBrowserErrors).sum(),
summary.stream().mapToLong(DailyReport::getOtherErrors).sum(),
}

但是对我来说,它看起来效率低下-有更好的方法吗?

2 个答案:

答案 0 :(得分:2)

您可以通过实现将报告“添加”到摘要对象的逻辑以及组合两个摘要对象的逻辑来减少数据流。

这是下面的样子:

//Adds a report to a summary
BiFunction<Summary, DailyReport, Summary> reportMerger = (summ, rep1) -> {
    Summary summary = new Summary();

    summary.setStartDate(rep1.getDay().isAfter(summ.getStartDate()) ? 
                rep1.getDay() : summ.getStartDate());
    summary.setEndDate(rep1.getDay().isAfter(summ.getEndDate()) ? 
                summ.getEndDate() : rep1.getDay());
    summary.setSumOfCritical(rep1.getCriticalErrors() 
                + summ.getSumOfCritical());
    summary.setSumOfBrowser(rep1.getBrowserErrors() 
                + summ.getSumOfBrowser());
    summary.setSumOfOthers(rep1.getOtherErrors() 
                + summ.getSumOfOthers());

    return summary;
};

//combines 2 summary objects
BinaryOperator<Summary> summaryMerger = (s1, s2) -> {
    Summary summ = new Summary();

    summ.setStartDate(s1.getStartDate().isBefore(s2.getStartDate()) ? 
                s1.getStartDate() : s2.getStartDate());
    summ.setEndDate(s1.getEndDate().isBefore(s2.getEndDate()) ? 
                s2.getEndDate() : s1.getEndDate());

    summ.setSumOfCritical(s1.getSumOfCritical() 
                + s2.getSumOfCritical());
    summ.setSumOfBrowser(s1.getSumOfBrowser() 
                + s2.getSumOfBrowser());
    summ.setSumOfOthers(s1.getSumOfOthers() 
                + s2.getSumOfOthers());

    return summ;
};

然后将报告流简化为一个摘要

Summary summary = dailyReports.stream()
     .reduce(new Summary(), reportMerger, summaryMerger);

注意:您需要在上述比较中为new Summary()的空字段添加空检查(以避免NPE)。


另一种收集方法(感谢Eugene的评论)消除了对新对象的需求:

Summary summaryTwo = dailyReports.stream().collect(Collector.of(Summary::new, 
    (summ, rep) -> {
        //add rep to summ
    }, (summary1, summary2) -> {
        //merge summary2 into summary1
        return summary1;
    }));

答案 1 :(得分:1)

您可以循环使用DailyReports并计算类似值

LocalDate startDate =  dailyReports.get(0).getDay;
LocalDate endDate =  dailyReports.get(dailyReports.size() - 1).getDay;

Long sumOfCritical=0L;
Long sumOfBrowser=0L;
Long sumOfOthers=0L;

dailyReports.stream().foreach(o->{ 
sumOfCritical += o.getCriticalErrors();
sumOfBrowser += o.getBrowserErrors();
sumOfOthers += o.getOtherErrors();
})

Summary summary = new Summary(startDate, endDate,sumOfCritical, sumOfBrowser, sumOfOthers)

如果您需要更多详细信息,可以转到know about stream apiknow about lambda expression