I was asked to retrieve every leaf node that is a descandant of a tree node. I quickly got the idea that I could do this job in one line!
public Set<TreeNode<E>> getLeaves() {
return getChildrenStream().flatMap(n -> n.getChildrenStream()).collect(toSet());
}
It was good at the first glance, but quickly it ran into a StackOverflowExcepetion
if the tree depth reaches ~10, something that I can't accept. Later I developed a implementation without recursion and stream (but with my brain roasted), but I'm still wondering if there is a way to do recursive flatMap
s with stream, because I found it impossible to do so without touching the stream internals. It'll need a new Op, like RecursiveOps
to do that, or I will have to collect all results into a Set
every step, and operate on that Set
later:
Set<TreeNode<E>> prev = new HashSet<>();
prev.add(this);
while (!prev.isEmpty()) {
prev = prev.stream().flatMap(n -> n.getChildrenStream()).collect(toSet());
}
return prev;
Not good as it seems to be. Streams are meant to be a pipeline. Its result and intermediate results are not computed until a terminal op is added. The above approach appearently violates that principle. It's not as easy to parellelize as streams, too. Can I recursively flatMap without manually computing all intermediate results?
PS1: the TreeNode declaration:
public class TreeNode<E> {
// ...
/**
* Get a stream of children of the current node.
*
*/
public Stream<TreeNode<E>> getChildrenStream(){
// ...
}
public Set<TreeNode<E>> getLeaves() {
// main concern
}
}f