Udo*_*Udo 48 java lambda java-8 java-stream
在Java8中运行以下流示例:
System.out.println(Stream
.of("a", "b", "c", "d", "e", "f")
.reduce("", (s1, s2) -> s1 + "/" + s2)
);
Run Code Online (Sandbox Code Playgroud)
收益率:
/a/b/c/d/e/f
Run Code Online (Sandbox Code Playgroud)
这是 - 当然 - 毫不奇怪.由于http://docs.oracle.com/javase/8/docs/api/index.html?overview-summary.html,流顺序执行还是并行执行无关紧要:
除了标识为显式非确定性的操作(例如findAny())之外,流是顺序执行还是并行执行不应更改计算结果.
AFAIK reduce()是确定性的并且(s1, s2) -> s1 + "/" + s2是关联的,因此添加parallel()应该产生相同的结果:
System.out.println(Stream
.of("a", "b", "c", "d", "e", "f")
.parallel()
.reduce("", (s1, s2) -> s1 + "/" + s2)
);
Run Code Online (Sandbox Code Playgroud)
但是我机器上的结果是:
/a//b//c//d//e//f
Run Code Online (Sandbox Code Playgroud)
这有什么不对?
BTW:使用(首选).collect(Collectors.joining("/"))而不是为顺序和并行执行reduce(...)产生相同的结果a/b/c/d/e/f.
JVM详细信息:
java.specification.version: 1.8
java.version: 1.8.0_31
java.vm.version: 25.31-b07
java.runtime.version: 1.8.0_31-b13
Run Code Online (Sandbox Code Playgroud)
Jar*_*lak 63
来自reduce的文档:
标识值必须是累加器函数的标识.这意味着对于所有t,accumulator.apply(identity,t)等于t.
在你的情况下不是这样 - ""和"a"创建"/ a".
我已经提取了累加器函数并添加了一个打印输出来显示发生了什么:
BinaryOperator<String> accumulator = (s1, s2) -> {
System.out.println("joining \"" + s1 + "\" and \"" + s2 + "\"");
return s1 + "/" + s2;
};
System.out.println(Stream
.of("a", "b", "c", "d", "e", "f")
.parallel()
.reduce("", accumulator)
);
Run Code Online (Sandbox Code Playgroud)
这是示例输出(运行之间不同):
joining "" and "d"
joining "" and "f"
joining "" and "b"
joining "" and "a"
joining "" and "c"
joining "" and "e"
joining "/b" and "/c"
joining "/e" and "/f"
joining "/a" and "/b//c"
joining "/d" and "/e//f"
joining "/a//b//c" and "/d//e//f"
/a//b//c//d//e//f
Run Code Online (Sandbox Code Playgroud)
您可以向函数添加if语句以分别处理空字符串:
System.out.println(Stream
.of("a", "b", "c", "d", "e", "f")
.parallel()
.reduce((s1, s2) -> s1.isEmpty()? s2 : s1 + "/" + s2)
);
Run Code Online (Sandbox Code Playgroud)
正如Marko Topolnik所注意到的那样,s2不需要检查,因为累加器不必是交换功能.
要添加到其他答案,
您可能希望使用Mutable reduction,doc指定执行类似的操作
String concatenated = strings.reduce("", String::concat)
Run Code Online (Sandbox Code Playgroud)
会给出糟糕的表现结果.
我们会得到理想的结果,甚至可以并行工作.但是,我们可能对性能不满意!这样的实现将进行大量的字符串复制,并且运行时间将是字符数的O(n ^ 2).更高效的方法是将结果累积到StringBuilder中,StringBuilder是用于累积字符串的可变容器.我们可以使用相同的技术来并行化可变缩减,就像我们使用普通缩减一样.
所以你应该使用StringBuilder.
| 归档时间: |
|
| 查看次数: |
3030 次 |
| 最近记录: |