java - 难道不能保证从列表派生的并行流总是表现得像它的顺序对应物一样,提供相同的、可预测的输出吗?
问题描述
以下代码打印了 100 次 true:
for(int i=0; i<100; i++) {
String s2 = Arrays.asList("A", "E", "I", "O", "U").parallelStream().reduce("x", String::concat, String::concat);
System.out.println("xAxExIxOxU".equals(s2));
}
当然,100 次并不是保证。但是,即使这里使用的身份不符合要求“...对于所有 u,combiner.apply(identity, u) 等于 u” ,我们仍然可以说,难道不是吗?从列表或任何其他固有有序结构派生的并行流的行为就像 reduce() 中返回相同输出的顺序流?
解决方案
带有标识参数的函数的JavadocStream.reduce
说:
标识值必须是累加器函数的标识。这意味着对于所有 t,accumulator.apply(identity, t) 等于 t。
这显然不是这里的情况 -"x".concat(anything)
不等于anything
。这里唯一有效的身份值是""
。
如果您已经测试了问题标题的前提- 通过查看非并行操作返回的内容 - 您会看到标题的答案是“否” - 因为"xAEIOU"
您的 reduce 操作返回了非并行流。
如果您将标识值从 更改"x"
为""
,那么答案将是“是的,有这样的保证,因为您的 reduce 函数是关联的,并且对标识值的约束也得到满足。”
即使您修改了标题,答案也很明确:
reduce
您通过提供一个不是您的 reduce 函数的标识值的值作为标识值来破坏函数的合同。因此,由于您违反了reduce
方法的合同,因此所有保证都无效。
创建一个不成立的案例很容易;就像 Holger 已经指出的那样,让你的列表更大:
List<String> list = new ArrayList<>();
for (int i = 0; i < 500; i++) {
list.add("A");
}
String s2 = list.parallelStream().reduce("x", String::concat, String::concat);
System.out.println(s2);
if (s2.length() != list.size() * 2) {
System.out.println("Bad s2 size");
}
推荐阅读
- ipfs - 同一文件的 CID 是否不同但由 IPFS 中的 2 个用户上传?
- c - Visual Studio Code:参数未传递给 C 命令行应用程序
- raspberry-pi - 为什么我的输入源在发送时没有改变
通过 CEC 客户端发送消息? - couchdb - 使用 couchdb 超级账本结构时加入对等通道时出错
- sbt - sbt-native-packager Inellij 中的未知工件
- javascript - 从 blob url 下载 video.mp4
- ios - iOS Xcode Swift - 如何获取热点连接设备的 IP 地址?
- php - 如何使用php从txt文件中读取所有第二行并将它们放入1个变量中
- python - 很多不一致的包
- flutter - 多个 WillPopScope?