Reputation: 1128
I have the following method that calls itself recursively:
public ArrayList<SpecTreeNode> getLeavesBelow()
{
ArrayList<SpecTreeNode> result = new ArrayList<>();
if (isLeaf())
{
result.add(this);
}
for (SpecTreeNode stn : chList)
{
result.addAll(stn.getLeavesBelow());
}
return result;
}
I'd like to convert the for loop to use parallelStream. I think I'm partly there but not sure how to implement .collect() to 'addAll' to result:
chList.parallelStream()
.map(SpecTreeNode::getLeavesBelow)
.collect();
Some assistance would be much appreciated.
Upvotes: 1
Views: 818
Reputation: 34470
I would do it by making the recursive method return a Stream
of nodes instead of a List
, then filter to keep only the leaves and finally collect to a 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));
}
Upvotes: 1
Reputation: 44210
Just like this, right? Am I missing something?
result.addAll(
chList.parallelStream()
.map(SpecTreeNode::getLeavesBelow)
.flatMap(Collection::stream)
.collect(Collectors.toList())
);
Unrelated to your question but because you're seeking performance improvements: you may see some gains by specifying an initial size for your ArrayList to avoid reallocating multiple times.
A LinkedList
may be a preferable data structure if you can't anticipate the size, as all you're doing here is continually appending to the end of the list. However, if you need to randomly access elements of this list later then it might not be.
Upvotes: 1