多有趣的问题啊。首先,我定义了一个简单的方法:
private static JournalDTO toDTO(JournalEntry entry) {
return new JournalDTO(entry.getId(), entry.getMessage(), new ArrayList<>());
}
比我定义的小计算
Map
(s)这将有助于我快速搜索:
Map<Integer, JournalEntry> identity = entries.stream()
.collect(Collectors.toMap(JournalEntry::getId, Function.identity()));
Map<Integer, Set<Integer>> map = entries.stream()
.collect(Collectors.groupingBy(
x -> x.getParentId() == null ? -1 : x.getParentId(),
Collectors.mapping(JournalEntry::getId, Collectors.toSet())));
第一个应该是明显的,它包含一个ID和一个
JournalEntry
.
第二个保持
parentId
到一组ID。基本上:
-1 == 1 // -1 meaning it has no parents
1 == 2 // 1 has a child with id 2
2 == 3, 4 // 2 has two children with id 3 and 4
4 == 5, 6 // ...
如果你考虑的话——这就是我如何找到一个完整的“家庭”的例子(如果这里需要更多的细节,请告诉我)。
其余的是简单的代码,使用递归方法:
// get those that have no parents first
Set<Integer> ids = map.get(-1);
// this is the ultimate result
List<JournalDTO> all = new ArrayList<>();
// for each entity with no parents, start searching in the map
ids.forEach(x -> {
JournalDTO parentDTO = toDTO(identity.get(x));
recursive(x, map, identity, parentDTO);
all.add(parentDTO);
});
当然,最重要的部分是:
private static void recursive(
Integer parentId,
Map<Integer, Set<Integer>> map,
Map<Integer, JournalEntry> identity,
JournalDTO journalDTO) {
Set<Integer> childrenIds = map.get(parentId);
if (childrenIds != null && !childrenIds.isEmpty()) {
childrenIds.forEach(x -> {
JournalDTO childDTO = toDTO(identity.get(x));
journalDTO.getChildEntries().add(childDTO);
recursive(x, map, identity, childDTO);
});
}
}
我已经测试了一个相当简单的案例
==
)对我来说似乎还不错。