【问题标题】:Traverse inheritance tree recursively with Java用Java递归遍历继承树
【发布时间】:2021-05-21 14:10:33
【问题描述】:

我需要获取给定记录并使用其所有子记录的标识符无限填充一个列表(即原始项目的所有子记录、子项的所有子记录、孙子的所有子记录等)我目前有一种方法可以产生我想要的东西,但它不是最容易阅读的方法,它使用迭代而不是递归。我想知道是否有一种更简洁的方法来实现我想要的,可能使用递归调用,但主要目的是使代码更易于阅读。目前的实现如下

public List<String> getAllChildRecords(targetRecord) {  
    
    final List<String> allChildRecordIds = new ArrayList<>();
    final List<String> recordIdsForQuery = new ArrayList<>();
    final List<String> queryResults = new ArrayList<>();

    recordIdsForQuery.add(targetRecord);

    while (!recordIdsForQuery .isEmpty()) {

        for (final String queryParentId : recordIdsForQuery ) {
            queryResults.addAll(
                    [DBAccessLayerClass].[getChildRecordIds](queryParentId));
        }

        allChildRecordIds .addAll(queryResults);
        recordIdsForQuery .clear();
        recordIdsForQuery .addAll(queryResults);
        queryResults.clear();
    }

    return allChildRecordIds 

}

【问题讨论】:

    标签: java recursion iteration


    【解决方案1】:

    递归通常不是正确的答案,尤其是在 java 中 - 例如,它往往很慢,并且会产生复杂的堆栈跟踪。因此,“只是重写为递归”不是一个很好的答案,因此,如果您担心可读性,也不是一个很好的改进。

    通常的技巧是使用队列。另外,停止将事情声明为“为了可读性”-您正在为这段代码添加大量噪音。如果您坚持将“更改本地人”减少到最低限度以提高可读性,请将您的 IDE 配置为以高度可见的方式将写入呈现给本地人,不要在任何地方添加一堆嘈杂的关键字来弄乱您的代码。

    var out = new ArrayList<String>();
    var queue = new ArrayDeque<String>();
    queue.add(targetRecord);
    
    while (!queue.isEmpty()) {
      String id = queue.pop();
      var childIds = DbAccessLayerClass.getChildRecordIds(id));
      out.addAll(childIds);
      queue.addAll(childIds);
    }
    
    return out;
    

    如果您害怕循环或重复(例如,其中一项可能是多个单独条目的子项),请将您的 out 改为 (Linked)HashSet,并在 @987654325 之后添加 childIds.removeAll(out); @。

    【讨论】:

    • 不幸的是,我必须保留所有这些最终关键字,这不是我可以更改的,但这看起来是一个非常有趣的解决方案,我以前没有真正使用过队列。非常感谢您的反馈,太好了:)
    • 这很好,我可能会添加使用queues vs stacks 会给你广度优先搜索和深度优先搜索,取决于问题领域和你的理解,你可以替换数据结构以获得更好的实践性能
    • @Bhaskar ArrayDeque 可以在任何一种方式下以高性能运行 - 使用 .pop() 或 .removeLast() 在深度优先和呼吸优先之间切换。
    • @rzwitserloot - 同意,你可能会注意到我没有说任何关于实现的内容。
    猜你喜欢
    • 2023-03-21
    • 2018-07-12
    • 2014-03-11
    • 1970-01-01
    • 2016-05-01
    • 1970-01-01
    • 2017-05-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多