我需要获取一个给定的记录,并用它的所有子记录和无限项的标识符填充一个列表(即原始项的所有子记录、子项的所有子记录、子项的所有子记录等)。我目前有一个方法可以产生我想要的东西,但它不是最容易阅读的,并且使用迭代而不是递归。我想知道是否有一种更干净的方法来实现我想要的,潜在地使用递归调用,但主要目的是使代码更容易阅读。当前实现如下所示
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 }
发布于 2021-02-18 23:43:38
递归通常不是正确的答案,特别是在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;如果您害怕循环或重复(例如,1项可以是多个单独条目的子项),请将out转换为(Linked)HashSet,并在DbAccessLayerClass.getChildRecordIds后面添加childIds.removeAll(out);。
https://stackoverflow.com/questions/66263103
复制相似问题