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

前端 未结 3 1825
轮回少年
轮回少年 2020-12-03 04:42

I created simple demo :

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


        
相关标签:
3条回答
  • 2020-12-03 05:12

    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

    0 讨论(0)
  • 2020-12-03 05:23

    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(...
    
    0 讨论(0)
  • 2020-12-03 05:29

    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
    
    0 讨论(0)
提交回复
热议问题