Summing

Let's assume that we want to sum all the weights of melons. We did this in the Sum, max, and min in a stream section via primitive specializations of Stream. Now, let's do it via the summingInt​(ToIntFunction<? super T> mapper) collector:

int sumWeightsGrams = melons.stream()
.collect(Collectors.summingInt(Melon::getWeight));

So, Collectors.summingInt() is a factory method that takes a function that's capable of mapping an object into an int that has to be summed as an argument. A collector is returned that performs the summarization via the collect() method. The following diagram depicts how summingInt() works:

While traversing the stream, each weight (Melon::getWeight) is mapped to its number, and this number is added to an accumulator, starting from the initial value, that is, 0.

After summingInt(), we have summingLong() and summingDouble(). How do we sum up the weights of melons in kilograms? This can be accomplished via summingDouble(), as follows:

double sumWeightsKg = melons.stream()
.collect(Collectors.summingDouble(
m -> (double) m.getWeight() / 1000.0d));

If we just need the result in kilograms, we can still perform the sum in grams, as follows:

double sumWeightsKg = melons.stream()
.collect(Collectors.summingInt(Melon::getWeight)) / 1000.0d;

Since summarizations are actually reductions, the Collectors class provides a reducing() method as well. Obviously, this method has a more general utilization, allowing us to provide all kinds of lambdas via its three flavors:

  • reducing​(BinaryOperator<T> op)
  • reducing​(T identity, BinaryOperator<T> op)
  • reducing​(U identity, Function<? super T,​? extends U> mapper, BinaryOperator<U> op)

The arguments of reducing() are pretty straightforward. We have the identity value for the reduction (as well as the value that is returned when there are no input elements), a mapping function to apply to each input value, and a function that's used to reduce the mapped values.

For example, let's rewrite the preceding snippet of code via reducing(). Notice that we start the sum from 0, convert it from grams into kilograms via a mapping function, and reduce the values (the resulted kilograms) via a lambda:

double sumWeightsKg = melons.stream()
.collect(Collectors.reducing(0.0,
m -> (double) m.getWeight() / 1000.0d, (m1, m2) -> m1 + m2));

Alternatively, we can simply convert to kilograms at the end:

double sumWeightsKg = melons.stream()
.collect(Collectors.reducing(0,
m -> m.getWeight(), (m1, m2) -> m1 + m2)) / 1000.0d;
Rely on reducing() whenever there is no suitable built-in solution. Think of reducing() as a generalized summarization.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset