I've a stream of MetricGroup
, where:
public class MetricGroup {
private int uploadedDocs;
private long uploadedKbs;
// getters and setters
}
I need to sumarize all metrics in one single metric. I mean, I need to add all metric.uploadedDocs
into a sumMetric.uploadedDocs
and metric.uploadedKds
into a sumMetric.uploadedKbs
.
I figure out I need some kind of reduce
Stream.of(new MetricGroup(1,100), new MetricGroup(1,200))
.reduce(????);
Any ideas?
Reducing is the repeated process of combining all elements. reduce operation applies a binary operator to each element in the stream where the first argument to the operator is the return value of the previous application and second argument is the current stream element.
A reduction is a terminal operation that aggregates a stream into a type or a primitive. The Java 8 Stream API contains a set of predefined reduction operations, such as average , sum , min , max , and count , which return one value by combining the elements of a stream.
There are a lot of benefits to using streams in Java, such as the ability to write functions at a more abstract level which can reduce code bugs, compact functions into fewer and more readable lines of code, and the ease they offer for parallelization.
The Stream API provides a rich repertoire of intermediate, reduction and terminal functions, which also support parallelization. More specifically, reduction stream operations allow us to produce one single result from a sequence of elements, by repeatedly applying a combining operation to the elements in the sequence.
You can use this overload of reduce
:
T reduce(T identity,
BinaryOperator<T> accumulator)
like this:
.reduce(new MetricGroup(0, 0),
(x, y) -> new MetricGroup(
x.getUploadedDocs() + y.getUploadedDocs()
x.getUploadedKbs() + y.getUploadedKbs()
)
)
You can also use the collect
method:
private static MetricGroup combine(MetricGroup x, MetricGroup y) {
x.setUploadedDocs(x.getUploadedDocs() + y.getUploadedDocs());
x.setUploadedKbs(x.getUploadedKbs() + y.getUploadedKbs());
return x;
}
// ....
.collect(() -> new MetricGroup(0, 0),
YourClass::combine,
YourClass::combine
)
To avoid the creation of several/many MetricGroup
objects during the reduce
call, you can make two separate calls to sum the UploadedDocs
and UploadedKbs
respectively and then construct a new MetricGroup
representing the result.
int uploadedDocsSum = source.stream().mapToInt(MetricGroup::getUploadedDocs).sum();
long uploadedKbsSum = source.stream().mapToLong(MetricGroup::getUploadedKbs).sum();
MetricGroup result = new MetricGroup(uploadedDocsSum, uploadedKbsSum);
Arguably more readable as well...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With