以下代码在每10-15次尝试相同输入时抛出illegalargumentexception:
AllDirectedPaths<Vertex, Edge> allDirectedPaths = new AllDirectedPaths<>(graph);
List<GraphPath<Vertex, Edge>> paths = allDirectedPaths.getAllPaths(entry, exit, true, null);
return paths.parallelStream().map(path -> path.getEdgeList().parallelStream()
.map(edge -> {
Vertex source = edge.getSource();
Vertex target = edge.getTarget();
if (source.containsInstruction(method, instructionIndex)) {
return source;
} else if (target.containsInstruction(method, instructionIndex)) {
return target;
} else {
return null;
}
}).filter(Objects::nonNull)).findAny().flatMap(Stream::findAny)
.orElseThrow(() -> new IllegalArgumentException("Given trace refers to no vertex in graph!"));
该代码的思想是找到一个顶点,该顶点封装了一条特定的指令(请参见 containsInstruction()
),而顶点至少位于 entry
到 exit
顶点。我知道代码在性能方面不是最优的(路径上的每个中间顶点都会被查找两次),但这并不重要。
输入只是一个跟踪(字符串),从中 method
以及 instructionIndex
可以导出。所有其他变量在这个意义上都是固定的。此外,该方法 containsInstruction()
没有任何副作用。
将'findany()'流操作放在哪里重要吗?我应该把它直接放在过滤操作之后吗?还是嵌套的并行流才是问题所在?
1条答案
按热度按时间nbewdwxp1#
你应该使用
.flatMap(path -> ... )
并移除.flatMap(Stream::findAny)
.你的代码不起作用,因为
findAny()
返回一个始终为非null的流,但该流可能null
元素。然后,当你申请第二个
findAny()
通过Optional.flatMap(Stream::findAny)
调用时,最后一次查找操作可能返回空值Optional
,结果是null
内部流的元素。代码应该是这样的:
旁白:为什么是平行流?管道中似乎没有cpu限制的任务。此外,并行流会产生大量开销。它们在极少数情况下非常有用,即数万个元素和流水线上密集的cpu操作
编辑:如评论中所建议的
map
以及filter
内流的操作可以安全地转移到外流。通过这种方式,可读性得到了提高,在性能方面没有任何区别:另一个注意事项:可能是重构内部代码
map
一种方法Edge
类会更好,以便逻辑返回源、目标或null
在已经拥有所有信息的类中。