【发布时间】:2016-05-10 14:01:10
【问题描述】:
我有一个家庭类,可以从 postgres 数据库中提取数据。这个类看起来像这样:
@Entity
public class Family(){
@Id
private long id;
private String firstName;
private String lastName;
private Long parentId;
private4 String familyPath;
private List<Family> children;
//getters and setters
在数据库中,我将它们彼此的关系存储为一个以句点分隔的字符串。例如,如果 Bob 是 Sue 的孩子,那么树列将如下所示:“bob.sue”。此路径作为家庭对象的一部分存储在 familyPath 变量中。
澄清 familyPath 是基于数据库中每一行的唯一 ID 的路径。所以路径可能看起来像“1.2.3”,其中最后一个数字是当前行。 “1.2.4”是另一条潜在路径。所以 ID 为 3 和 4 的行是 2 的子代,依此类推。
在我的代码中,我在数据库中查询数据中的所有家庭成员,因此我在数据库中有一组家庭的每个成员。我的目标是使用这个初始的平面集生成一组所有家庭成员作为层次结构。所以,最后如果我在 Bob 上调用 getChildren,我会得到一个包含 Sue 和任何其他孩子的列表。
我的解决方案:
首先,我遍历我的家庭列表,并找到我称之为根成员的东西——那些位于家庭路径顶层的成员——并将它们删除到一个单独的列表中。所以现在我有一份*家庭成员的名单,还有一份其他人的名单。
然后,对于*列表中的每个成员,我调用以下递归方法:
private Family familyTree(Family root, List<Family> members) {
List<Family> children = new ArrayList<>();
for (Family f : members) {
if (isChildOf(f, root)) {
children.add(familyTree(f, resources));
}
}
root.setChildren(children);
return root;
}
private boolean isChildOf(Family a, Family b) {
String pCPath = a.getFamilyPath();
String pPPath = b.getFamilyPath();
return pCPath.indexOf('.') >= 0
&& pCPath.substring(0, pCPath.lastIndexOf('.')).equals(pPPath);
}
并将输出保存到列表中。这会产生所需的结果。
我的问题 但是,我觉得这种递归方法非常昂贵(n^2)。我在想可能有一种更有效的方法来使用集合、映射和 Family 对象的 familyPath 变量来生成这个层次结构,但是我一直陷入多个迭代循环中。有人有想法吗?
【问题讨论】:
-
请添加isChildOf的代码
-
添加到递归函数的代码块
-
我还在数据库中添加了一个 parentId 列,并为模型添加了一个相应的变量。所以现在每个家庭对象都有其父对象的 id
标签: java database recursion hashmap hierarchy