递归返回集合中的集合或元素

时间:2016-02-16 03:44:45

标签: java recursion groovy closures static-typing

这是一个简单的递归算法,用于从树的叶子生成嵌套列表:

/** Make a list from bottom level of equal path tree - list would be nested according
    to hierarchy in tree.

     1
    /  \
   2    3
   /\   |
  4  5  6
    ==>
    [[4, 5], 6]
 */
List leavesToList(TreeNode node) {
    List<TreeNode> children = node.getChildren()
    if (!children) {
        return node.getData() // Problem with static typing!!
    }
    if (children.size() == 1) {
        return leavesToList(children[0])
    }
    return children.collect {leavesToList(it)}
}

该算法适用于动态类型,但静态类型会导致问题为非列表 函数无法返回值。理想情况下,对于这种情况,返回值 将是Collection<T>|T类型,但这种类型规范是不可能的。

作为一项工作,我想到了一个像这样的包装解决方案:

@CompileStatic
static List leavesToList(Tnode rnode) {
    Closure inner
    inner = { Tnode node ->
        List<Tnode> children = node.getChildren()
        if (!children) {
            return node.getData()
        }
        if (children.size() == 1) {
            return inner.call(children[0])
        }
        return children.collect { inner.call(it) }
    }
    return inner.call(rnode) as List
}

问题:

  • 包装器实现的效率是否低于原始实现? 例如,是否有重复设置闭包的开销?

  • 作为一种通用技术(而不是针对示例案例的特定技巧),是否存在 除了使用包装器之外,处理这种情况的更好方法是什么?

1 个答案:

答案 0 :(得分:2)

我希望我不会在这里遗漏一些东西,但为了静态打字,我会做这样的事情:

ExpiresByType image/gif "modification plus 1 month"

基本上将@CompileStatic List leavesToList(TreeNode node) { List<TreeNode> children = node.children if (!children) { return [node.data] } if (children.size() == 1) { return leavesToList(children.first()) } children.collect this.&leavesToList } 包装到列表中。