Stream.collect方法中的组合器如何在java 8中工作?

Vov*_*mer 27 java java-8 java-stream

我创建了简单的演示:

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

String collect = list2.stream().collect(String::new, (res, elem) -> {
              res=res.concat(" ").concat(elem);
//            System.out.printf("res=%s, elem=%s\n", res.isEmpty(), elem);

        }, (res1, res2) -> {
            System.out.printf("res1=%s, res2=%s\n", res1, res2);            
        });
        System.out.println("collect=" + collect);
}
Run Code Online (Sandbox Code Playgroud)

问题是BiConsumer combiner部分collect根本没有运行.

如果我使用parallelStream()两个参数res1并且res2等于供应商,它就会运行String::new.

如何combinercollect方法中工作?

Ran*_*niz 24

首先,不需要在非并行流中执行组合器,因为没有什么可以组合.

其次,你的问题源于使用String::newString.concat.累加器应该通过将第二个参数与它组合来修改第一个参数,但由于Java中的字符串是不可变的,因此您的代码不会产生任何结果.

          res=res.concat(" ").concat(elem);
Run Code Online (Sandbox Code Playgroud)

将创建一个新的字符串,然后扔掉它.您想要使用StringBuilder,以便保留中间结果:

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);
}
Run Code Online (Sandbox Code Playgroud)

这也适用于并行流

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


Era*_*ran 7

我认为它combiner仅用于并行Streams(用于组合并行计算的部分输出),因此使您的Stream并行.

String collect = list2.parallelStream().collect(...
Run Code Online (Sandbox Code Playgroud)

  • 没有什么可以阻止你更新你的答案...我认为有趣的部分是解释OP做错了什么和_"如何在收集方法中使组合器工作?"_(尽管累加器也是错误的) (3认同)
  • 请参阅[本教程](https://docs.oracle.com/javase/tutorial/collections/streams/reduction.html#collect) (2认同)

GKi*_*lin 5

对于Raniz样本,有和没有并行结果更为有趣:

    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();
Run Code Online (Sandbox Code Playgroud)

如果没有并行合并,永远不会被调用:

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
Run Code Online (Sandbox Code Playgroud)

并行

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
Run Code Online (Sandbox Code Playgroud)