【发布时间】:2020-01-20 05:13:41
【问题描述】:
谁能指出我正确的方向,因为我无法理解这个问题。
我正在执行以下方法。
private static void reduce_parallelStream() {
List<String> vals = Arrays.asList("a", "b");
List<String> join = vals.parallelStream().reduce(new ArrayList<String>(),
(List<String> l, String v) -> {
l.add(v);
return l;
}, (a, b) -> {
a.addAll(b);
return a;
}
);
System.out.println(join);
}
打印出来
[null, a, null, a]
我不明白为什么它会在结果列表中放置两个 null。我希望答案是
[a, b]
因为是并行流所以第一个参数要reduce
新的 ArrayList()
可能会为每个输入值 a 和 b 调用两次。
那么累加器函数可能会被调用两次,因为它是一个并行流,并在每次调用中传递每个输入“a 和 b”以及种子值提供的列表。因此 a 被添加到列表 1 中,b 被添加到列表 2 中(反之亦然)。之后组合器将合并两个列表,但它不会发生。
有趣的是,如果我在累加器中放置一个打印语句来打印输入的值,那么输出会发生变化。所以关注
private static void reduce_parallelStream() {
List<String> vals = Arrays.asList("a", "b");
List<String> join = vals.parallelStream().reduce(new ArrayList<String>(),
(List<String> l, String v) -> {
System.out.printf("l is %s", l);
l.add(v);
System.out.printf("l is %s", l);
return l;
}, (a, b) -> {
a.addAll(b);
return a;
}
);
System.out.println(join);
}
这个输出的结果
l 是 []l 是 [b]l 是 [b, a]l 是 [b, a][b, a, b, a]
谁能解释一下。
【问题讨论】:
-
ArrayList 不是线程安全的集合,因此任何并发调用都可能导致意外行为。另一方面,在使用 System.out.println 时,有一个隐藏的同步机制。当您使用synchronized list 时会发生什么?
-
coderanch上有一个有趣的解释
-
就像Why does Java stream map reduce count my result twice? 一样,可能还有其他一些错误使用
reduce的例子。阅读the package documentation(两个部分,“归约操作”和“可变归约”)也可能有所帮助。
标签: java java-8 java-stream reduce