用Java递归遍历继承树

用Java递归遍历继承树,java,recursion,iteration,Java,Recursion,Iteration,我需要获取一个给定的记录,并用其所有子记录的标识符(即原始项的所有子记录、子项的所有子记录、孙辈的所有子记录等)填充一个列表我目前有一个方法,可以产生我想要的东西,但它不是最容易阅读的,并且使用迭代而不是递归。我想知道是否有更干净的方法来实现我想要的,可能使用递归调用,但主要目的是使代码更易于阅读。目前的执行情况如下 public List<String> getAllChildRecords(targetRecord) { final List<Stri

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

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 
公共列表getAllChildRecords(targetRecord){
最终列表AllChildRecordId=new ArrayList();
最终列表recordIdsForQuery=new ArrayList();
最终列表queryResults=new ArrayList();
recordIdsForQuery.add(targetRecord);
而(!recordIdsForQuery.isEmpty()){
for(最终字符串queryParentId:recordIdsForQuery){
queryResults.addAll(
[DBAccessLayerClass]。[GetChildRecordId](queryParentId));
}
AllChildRecordId.addAll(查询结果);
recordIdsForQuery.clear();
recordIdsForQuery.addAll(queryResults);
queryResults.clear();
}
返回所有ChildRecordId

}

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

通常的技巧是处理队列。另外,不要再“为了可读性”而声明final了——这会给代码增加很多噪音。如果您坚持将“更改局部变量”的可读性降低到最低限度,请将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;
var out=new ArrayList();
var queue=new ArrayDeque();
queue.add(targetRecord);
而(!queue.isEmpty()){
String id=queue.pop();
var childIds=DbAccessLayerClass.getChildRecordIds(id));
out.addAll(childid);
queue.addAll(childid);
}
返回;

如果您害怕循环或重复(例如,其中一个项目可以是多个单独项目的子项),请将
out
转换为
(链接)HashSet
,然后添加
childId.removeAll(out)
紧接着
DbAccessLayerClass.getChildRecordId

不幸的是,我必须保留所有最后的关键字,这不是我可以更改的,但这看起来是一个非常有趣的解决方案,我以前从未真正使用过队列。非常感谢您的反馈,非常好:)这很好,我可能会添加使用
队列
vs
堆栈
将根据问题领域和您的理解,为您提供广度优先搜索vs深度优先搜索,您可以替换数据结构以在实践中获得更好的效果performance@Bhaskar
ArrayDeque
可以以任何一种方式在高性能下运行—使用.pop()或
.removeLast()
在深度优先和呼吸优先之间切换。@rzwitserroot-同意,您可能会注意到我没有说任何关于实现的内容。