How does combiner in Stream.collect method work in java 8?

Solution 1:

First off, there is no need for the combiner to be executed in a non-parallel stream since there is nothing to combine.

Secondly, your issue stems from using String::new and String.concat. The accumulator is supposed to modify the first argument by combining the second argument with it but since strings in Java are immutable your code will produce nothing.

          res=res.concat(" ").concat(elem);

will create a new string and then throw away it. You want to use a StringBuilder instead so you can keep the intermediate results:

public static void main(String[] args) {
    List<String> list2 = Arrays.asList("adf", "bcd", "abc", "hgr", "jyt", "edr", "biu");

    String collect = list2.stream().collect(StringBuilder::new, (res, elem) -> {
        res.append(" ").append(elem);
    }, (res1, res2) -> {
        res1.append(res2.toString());
        System.out.printf("res1=%s, res2=%s\n", res1, res2);
    }).toString();
    System.out.println("collect=" + collect);
}

This will also work correctly with a parallel stream

res1= hgr jyt, res2= jyt
res1= bcd abc, res2= abc
res1= adf bcd abc, res2= bcd abc
res1= edr biu, res2= biu
res1= hgr jyt edr biu, res2= edr biu
res1= adf bcd abc hgr jyt edr biu, res2= hgr jyt edr biu
collect= adf bcd abc hgr jyt edr biu

Solution 2:

I think that the combiner is only used in parallel Streams (to combine the partial outputs of the parallel computations), so make your Stream parallel.

String collect = list2.parallelStream().collect(...

Solution 3:

It is more interesting result with and without parallel for Raniz sample:

    String collect = list2.stream().collect(StringBuilder::new,
            (res, elem) -> {
                System.out.printf("ACCUMULATE res=%s, elem=%s\n", res, elem);
                res.append(" ").append(elem);
        },
            (res1, res2) -> {
                System.out.printf("COMBINE res1=%s, res2=%s\n", res1, res2);
                res1.append(res2.toString());
            }).toString();

Without parallel combine never have been called:

ACCUMULATE res=, elem=adf
ACCUMULATE res= adf, elem=bcd
ACCUMULATE res= adf bcd, elem=abc
ACCUMULATE res= adf bcd abc, elem=hgr
ACCUMULATE res= adf bcd abc hgr, elem=jyt
ACCUMULATE res= adf bcd abc hgr jyt, elem=edr
ACCUMULATE res= adf bcd abc hgr jyt edr, elem=biu
collect= adf bcd abc hgr jyt edr biu

And with parallel

ACCUMULATE res=, elem=jyt
ACCUMULATE res=, elem=hgr
COMBINE res1= hgr, res2= jyt
ACCUMULATE res=, elem=biu
ACCUMULATE res=, elem=edr
COMBINE res1= edr, res2= biu
ACCUMULATE res=, elem=bcd
COMBINE res1= hgr jyt, res2= edr biu
ACCUMULATE res=, elem=abc
ACCUMULATE res=, elem=adf
COMBINE res1= bcd, res2= abc
COMBINE res1= adf, res2= bcd abc
COMBINE res1= adf bcd abc, res2= hgr jyt edr biu
collect= adf bcd abc hgr jyt edr biu