我被要求检索作为树节点的descandant的每个叶节点。我很快意识到我可以在一条线上完成这项工作!
public Set<TreeNode<E>> getLeaves() {
return getChildrenStream().flatMap(n -> n.getChildrenStream()).collect(toSet());
}
第一眼看上去很好,但如果树深达到10,很快会遇到StackOverflowExcepetion
,这是我无法接受的。后来我开发了一个没有递归和流的实现(但我的大脑烤),但是我仍然想知道是否有办法用流做递归flatMap
,因为我发现如果不触及流内部,就不可能这样做。它需要一个新的操作系统,例如RecursiveOps
,或者我必须在每个步骤中将所有结果收集到Set
中,然后对Set
进行操作:< / p>
Set<TreeNode<E>> prev = new HashSet<>();
prev.add(this);
while (!prev.isEmpty()) {
prev = prev.stream().flatMap(n -> n.getChildrenStream()).collect(toSet());
}
return prev;
看起来并不好。流是一个管道。在添加终端操作之前,不会计算其结果和中间结果。上述方法显然违反了这一原则。它也不像溪流那样容易混淆。我可以递归flatMap而无需手动计算所有中间结果吗?
PS1:TreeNode声明:
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
答案 0 :(得分:0)
不完全确定这是否是您感兴趣的内容:
public static Set<TreeNode<String>> getAllLeaves(TreeNode<String> treeNode) {
final Stream<TreeNode<String>> childrenStream = treeNode.getChildrenStream();
if (childrenStream == null) {
return new HashSet<>();
}
Set<TreeNode<String>> ownLeaves = treeNode.getLeaves();
ownLeaves.addAll(childrenStream.flatMap(stringTreeNode -> getAllLeaves(stringTreeNode).parallelStream())
.collect(Collectors.toSet()));
return ownLeaves;
}
开箱即用,我发现这种方法有些不便之处。它确实为最后一次迭代返回一个空集,它正在创建流,就像flatMap
一样。但是我相信这是你正在寻找的,因为你正在考虑使用flatMap
从你想要的地方获得一个递归创建的连接集,其中首先没有创建流。顺便说一下,我已经尝试过-1000级了,它仍然可以很快地运行,没有问题。