I've been reading up on reduce and have just found out that there is a 3 argument version that can essentially perform a map reduce like this:
String[] strarr = {"abc", "defg", "vwxyz"};
System.out.println(Arrays.stream(strarr).reduce(0, (l, s) -> l + s.length(), (s1, s2) -> s1 + s2));
However I can't see the advantage of this over a mapToInt with a reduce.
System.out.println(Arrays.stream(strarr).mapToInt(s -> s.length()).reduce(0, (s1, s2) -> s1 + s2));
Both produce the correct answer of 12, and both appear to work fine in parallel.
Is one better than the other, and if so, why?
Is one better than the other, and if so, why?
With the first reduce
approach there’s an insidious boxing cost.
The mapToInt.reduce(...)
approach avoids that.
So, the idea is if you're interested in summation, average et al just use the primitive stream specializations as they're more efficient.
By the way, the code:
Arrays.stream(strarr).mapToInt(s -> s.length()).reduce(0, (s1, s2) -> s1 + s2)
can be simplified to:
Arrays.stream(strarr).mapToInt(s -> s.length()).sum();
The three-argument Stream.reduce
is more flexible:
<U> U reduce(U identity,
BiFunction<U, ? super T, U> accumulator,
BinaryOperator<U> combiner);
in comparison with the two-argument IntStream.reduce
that accepts and returns only int
values:
int reduce(int identity, IntBinaryOperator op);
While accumulator
in the three-argument version can accept parameters of two different types:
BiFunction<Integer, String, Integer> acc = (i, str) -> i + str.length();
that allows you to omit additional map
operation:
Arrays.stream(strs).reduce(0, (i, str) -> i + str.length(), Integer::sum)
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