Stream.collect 方法中的 combiner 在 java 8 中是如何工作的?

2022-09-01 11:52:17

我创建了简单的演示:

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);
}

问题是,这部分根本没有运行。BiConsumer combinercollect

如果我只使用两个参数并且等于供应商,它就会运行。parallelStream()res1res2String::new

如何使工作在方法上?combinercollect


答案 1

首先,不需要在非并行流中执行合并器,因为没有要组合的内容。

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

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

将创建一个新字符串,然后将其丢弃。您希望改用 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);
}

这也将正确用于并行流

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


答案 2

我认为 仅在并行流中使用(以组合并行计算的部分输出),因此使流并行。combiner

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

推荐