将 for loop 替换为 parallelStream - Java



我有以下递归调用自己的方法:

public ArrayList<SpecTreeNode> getLeavesBelow()
   {
      ArrayList<SpecTreeNode> result = new ArrayList<>();
      if (isLeaf())
      {
         result.add(this);
      }
      for (SpecTreeNode stn : chList)
      {
         result.addAll(stn.getLeavesBelow());
      }
      return result;
   }

我想将 for 循环转换为使用并行流。我想我部分在那里,但不确定如何将 .collect(( 实现为"addAll"以结果:

chList.parallelStream()
             .map(SpecTreeNode::getLeavesBelow)
             .collect();

如能提供一些援助,将不胜感激。

就像这样,对吧?我错过了什么吗?

result.addAll(
    chList.parallelStream()
         .map(SpecTreeNode::getLeavesBelow)
         .flatMap(Collection::stream)
         .collect(Collectors.toList())
);

与您的问题无关,但因为您正在寻求性能改进:通过为 ArrayList 指定初始大小以避免多次重新分配,您可能会看到一些收益。

如果您无法预测大小,则LinkedList可能是更可取的数据结构,因为您在此处所做的只是不断追加到列表的末尾。但是,如果您稍后需要随机访问此列表的元素,则可能不需要。

我会通过让递归方法返回节点Stream而不是List来做到这一点,然后过滤以仅保留叶子并最终收集到列表中:

public List<SpecTreeNode> getLeavesBelow() {
    return nodesBelow(this)
        .parallel()
        .filter(Node::isLeaf)
        .collect(Collectors.toList());
}
private Stream<SpecTreeNode> nodesBelow(SpecTreeNode node) {
    return Stream.concat(
               Stream.of(node), 
               node.chList.stream()
                      .flatMap(this::leavesBelow));
}

最新更新