并行流API减少方法

时间:2020-09-27 14:21:58

标签: java java-stream

我正在学习Stream api,并且停留在Stream的reduce方法上。我有一些字符串流,我想连接它们。下面是我的代码段。

Stream<String> data = Stream.of("a", "b", "c", "d", "e", "f");

String col = data.parallel().reduce("dummy",

            (t, u) -> {
                
                return t + " : " + u;

            },

            (a, b) -> {
                return a + b;
            });

System.out.println(col);

//Output: dummy : adummy : bdummy : cdummy : ddummy : edummy : f
//Expected: dummy : a : b : c : d : e : f

//I don't want them in sequence but at least they should not have repeated "dummy" String.

这将导致输出奇怪。请帮助我在这里找到问题所在。

2 个答案:

答案 0 :(得分:1)

上面的reduce不起作用的原因是因为'标识值必须是组合器函数的标识。这意味着对于所有u,combiner(identity,u)等于u。'

'dummy'不是String串联的有效标识,因为dummy + value不等于value。用这样的东西替换应该可以工作:

    public static void main(String args[])
    {
        Stream<String> data = Stream.of("a", "b", "c", "d", "e", "f");
        System.out.println(data.parallel().reduce("", Test::accumulate));
    }

    private static String accumulate(String v1, String v2)
    {
        if(v1.isEmpty()) return v2;
        if(v2.isEmpty()) return v1;
        return v1 +":" + v2;
    }

作为另一种选择,假设仅包含“虚拟”,是因为reduce期望提供初始状态,类似这样的事情可能对您有用:

data.parallel().reduce((v1, v2) -> v1 +":" + v2).orElse("???");

or

data.parallel().collect(Collectors.joining(":"));

编辑-为什么减少这种行为?

在同时聚合数据时,需要做出某些假设。例如,流中元素的合并顺序不应影响结果的有效性。为了解决这个问题,在归约运算中可能使用的功能类型存在某些限制。一个限制是:

'标识值必须是组合器功能的标识。这意味着对于所有u,combiner(identity,u)等于u。'

这样,至少我们可以说在功能上没有理由为什么并行执行身份不能传递给所有元素。考虑以下原因可能有用:

  1. 如果仅允许将第一个元素与标识组合在一起,从计算角度看是什么意思?
  2. 如果我还想立即开始处理第二个元素怎么办?

(有关更多详细信息,请参见此答案:https://stackoverflow.com/a/51290673/14294525

答案 1 :(得分:1)

您也可以不使用reduce来使用以下内容,

Stream<String> data = Stream.of("a", "b", "c", "d", "e", "f");
String output = data.parallel().collect(Collectors.joining(" : ", "dummy : ", ""));
相关问题