当前位置: 首页 > 知识库问答 >
问题:

如何递归flatMap流?[副本]

方嘉志
2023-03-14

我被要求检索树节点的每个叶节点。我很快想到我可以在一行中完成这项工作!

public Set<TreeNode<E>> getLeaves() {
    return getChildrenStream().flatMap(n -> n.getChildrenStream()).collect(toSet());
}

第一眼看上去很不错,但很快它就遇到了一个StackAfExcepetion,如果树深度达到~10,这是我无法接受的。后来我开发了一个没有递归和流的实现(但我的大脑被烤坏了),但我仍然想知道是否有一种方法可以用流做递归平面图,因为我发现不接触流内部是不可能做到的。它需要一个新的Op,比如RecursiveOps来做到这一点,否则我必须每一步都将所有结果收集到Set中,然后再对该Set进行操作:

Set<TreeNode<E>> prev = new HashSet<>();
prev.add(this);
while (!prev.isEmpty()) {
    prev = prev.stream().flatMap(n -> n.getChildrenStream()).collect(toSet());
}
return prev;

不像看起来那么好。流意味着管道。它的结果和中间结果直到添加了一个终端op才被计算。上述方法显然违反了这一原则。它也不像流那样容易并行化。我可以递归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

共有1个答案

邬英武
2023-03-14

不完全确定这是否是您感兴趣的内容:

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;
}

开箱即用,我看到了这个方法的一些不方便之处。它确实为最后一次迭代返回了一个空的Set,并且它正在创建流,就像它在平地图一样。然而,我相信这就是你正在寻找的,因为你正在考虑使用平地图,从那里你想得到一个递归创建的连接集,而在那里没有创建流。顺便说一句,我已经用-1000级别尝试过了,它仍然工作得相当快,没有问题。

 类似资料:
  • 问题内容: 我想使用Java 8递归列出计算机上的所有文件。 Java 8提供了一种返回所有文件和目录但不递归的方法。如何使用它来获取完整的文件递归列表(不使用变异集合)? 我尝试了下面的代码,但仅深入了一层: 而且使用不会编译(不确定原因)… 注意:我对涉及FileVisitors或外部库的解决方案不感兴趣。 问题答案: 通过递归遍历文件系统生成路径路径流的新API是。 如果您真的想递归地生成流

  • 并使用不编译(不确定原因)... 注意:我对涉及FileVisitors或外部库的解决方案不感兴趣。

  • 我有一些教科书式的代码,它以递归方式调用自己。我不了解程序流。代码如下: 在Recur_Factorial_Data中,我循环遍历数据元素并调用Recur_Factorial,它将其值返回给调用函数(Recur_Factorial_Data)。我预计标记为2(“返回num”)和3(“返回结果”)的行将始终返回一个值给调用函数,但事实并非如此。例如,初始值(来自数组DataArray)为11,函数重

  • 问题内容: 如何递归所有目录和子目录? 问题答案: 第一个参数表示要搜索的正则表达式,而第二个参数表示应搜索的目录。在这种情况下,表示当前目录。 注意:这适用于GNU grep,在某些平台(如Solaris)上,必须专门使用GNU grep而不是传统实现。对于Solaris,这是命令。

  • 问题是使用reduce()对数组数组进行操作,并返回一个没有子数组的同构数组。例如-[1,2,[3,[4,5]]]将返回[1,2,3,4,5]。 下面是工作的代码,考虑到子数组本身不是另一个数组的数组- 请注意,我更改了arr数组,因为代码不适用于第一个arr数组,即[1,2,a,b,C]。对于arr[1,2,3,4,C],返回的对象是[1,2,3,4,9,10] 它将我的函数oneArray解释

  • 问题内容: 请以最简单的方式说明递归的工作方式。 问题答案: 这是一个递归方法的简单示例:-