Example of stream reduction with distinct combiner and accumulator
If the combiner and accumulator are the same? You are confusing things here.
accumulator
transforms from X
to Y
for example (using the identity), while combiner
merges two Y
into one. Also notice that one is a BiFunction
and the other one is a BinaryOperator
(which is actually a BiFunction<T, T, T>
).
Is there an example of stream reduction with distinct combiner and accumulator?
These look pretty different to me:
Stream.of("1", "2")
.reduce(0, (x, y) -> x + y.length(), Integer::sum);
I think you might be confused with things like:
Stream.of("1", "2")
.reduce("", String::concat, String::concat);
How is it possible to do?
BiFunction<String, String, String> bi = String::concat;
Well there is a hint here.
EDIT
Addressing the part where "different" means different operations, accumulator
might sum
, while accumulator
might multiply
. This is exactly what the rule :
combiner.apply(u, accumulator.apply(identity, t)) == accumulator.apply(u, t)
is about, to protected itself from two separate associative functions, but different operations. Let's take an example of two lists (equal, but with different order). This, btw, would be a lot funner with a Set::of
from java-9
that adds an internal randomization, so theoretically for the same exact input, you would get different result on the same VM from run to run. But to keep it simple:
List.of("a", "bb", "ccc", "dddd");
List.of("dddd", "a", "bb", "ccc");
And we want to perform:
....stream()
.parallel()
.reduce(0,
(x, y) -> x + y.length(),
(x, y) -> x * y);
Under the current implementation, this will yield the same result for both lists; but that is an implementation artifact.
There is nothing stopping an internal implementation in saying: "I will split the list to the smallest chunk possible, but not smaller than two elements in each of them". In such a case, this could have been translated to these splits:
["a", "bb"] ["ccc", "dddd"]
["dddd", "a" ] ["bb" , "ccc" ]
Now, "accumulate" those splits:
0 + "a".length = 1 ; 1 + "bb".length = 3 // thus chunk result is 3
0 + "ccc".length = 3 ; 3 + "dddd".length = 7 // thus chunk result is 7
Now we "combine" these chunks: 3 * 7 = 21
.
I am pretty sure you already see that the second list in such a scenario would result in 25
; as such different operations in the accumulator and combiner can result in wrong results.