You can reduce a stream by implementing the logic of "adding" a report to a summary object, and the logic of combining two summary objects.
Here's what that looks like:
//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;
};
And then reduce a stream of reports into a single summary
Summary summary = dailyReports.stream()
.reduce(new Summary(), reportMerger, summaryMerger);
Note: you need to add null checks for the null fields of new Summary()
in the comparisons above (to avoid NPEs).
An alternative way to collect (thanks to Eugene's comments) that removes the need for new objects:
Summary summaryTwo = dailyReports.stream().collect(Collector.of(Summary::new,
(summ, rep) -> {
//add rep to summ
}, (summary1, summary2) -> {
//merge summary2 into summary1
return summary1;
}));