我将展示一个简化的问题示例来帮助演示它。
假设我正在尝试将旧的Java代码转换为java 8代码以实现样式和并行化(我这样做)。
这是代码:
public static boolean deleteTester(List<Integer> keys) {
DHeap dHeap = new DHeap(d, keys.size());
DHeap_Item[] DHeap_ItemArray = keysListToDHeap_ItemArray(keys);
dHeap.arrayToHeap(DHeap_ItemArray);
for (int i = 0; i < keys.size(); i++) {
keys.set(i, null);
dHeap.delete(DHeap_ItemArray[i]);
if (!someTest(keys, dHeap.getList()))
return false;
}
return true;
}
转化有几个问题:
这是我尝试替换for循环:
return IntStream.range(0, keys.size())
//.parallel()
.peek(idx -> keys.set(idx, null))
.peek(idx -> dHeap.delete(DHeap_ItemArray[idx]))
.allMatch(e -> someTest(keys, dHeap.getList()));
更短且可读,但“违反了规则”,结果无法并行。
所以我的问题是:
.parallal()
? (我得到一个空指针ex。)我猜答案是相互交织的。 我刚刚开始学习java 8,所以非常感谢所有的帮助,因为我真的被卡住了。
答案 0 :(得分:2)
问:为什么我无法使用.parallal()?
问:访问外部元素时该怎么办?
你可以在并行流中使用它,当动作没有修改那里的共享状态时没有问题,例如:
curl "url"
如果操作修改共享状态,则它负责提供所需的同步,例如:
stream.peek(System.out::println).allMatch(...);
问:为什么我们不应该使用peek()?
您可以使用stream.peek(it->{synchronized(lock){ keys.set(idx, null); }}).allMatch(...);
方法,但如果您无法控制流,则应避免使用peek()
,例如:
peek()
问:我该如何转移&#34; java 8流的代码?
详细说明了如何在包汇总java.util.stream中操作流。
答案 1 :(得分:1)
你绝对不应该像这样使用peek
。 Streams API文档未指定元素仅在peek
中的测试失败之前才会通过allMatch
。流中的所有下注都是并行的,因为anyMatch
不需要按顺序进行评估,即使另一个线程遇到违反{{1}的条件,也允许一个线程继续执行peek
}。
即使流是连续的,anyMatch
在某些情况下也可以执行意外的次数。请考虑以下代码:
peek
您可能认为它会打印最多3个数字,但事实上它会打印最多5个数字。