我正在尝试对一些实体进行分组,以将孩子放在父级上。
@Entity
public class JournalEntry {
Integer id;
String message;
Integer parentId;
}
数据传输对象看起来像这样...
public class JournalDTO {
public JournalDTO (Integer id, String message, List<JournalDTO> childEntries) {
this.id = id;
this.message = message;
this.childEntries = childEntries;
}
Integer id;
String message;
List<JournalDTO> childEntries;
}
因此,我希望以一个没有父ID的List结束,而顶层则没有父ID,然后它们将具有一组子实体,并且在这些子实体中,它们也可能具有子实体。有没有办法做到这一点。我的想法是首先获得所有顶级条目,如下所示。
List<JournalEntry> journalEntries = service.fetchJournalEntries();
List<JournalEntry> topLevel = journalEntries.stream().filter(e -> null==e.getParentId()).collect(toList());
journalEntries.removeAll(topLevel);
List<JournalDTO> journalDTOs = topLevel.stream()
.map(tl -> new JournalDTO(tl.getId(), tl.getMessage(), new ArrayList<JournalDTO>()))
.collect(toList());
然后我将其余条目按父ID分组。
Map<Integer, List<JournalEntry>> childMap = journalEntries.stream().collect(groupingBy(Integer::getParentId));
然后,我可以遍历此映射并将childEntities添加到父实体,但这只会给我第二级,然后我必须确保没有子代的孩子,等等。有没有更好的方法?
多么有趣的问题。首先,为了简单起见,我定义了一种方法:
private static JournalDTO toDTO(JournalEntry entry) {
return new JournalDTO(entry.getId(), entry.getMessage(), new ArrayList<>());
}
比我定义的一些小计算Map
可以帮助我快速搜索:
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和一个ID配对JournalEntry
。
第二个将parentId
s 保留为一组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);
});
}
}
我已经针对一个非常简单的案例(带有的案例==
)进行了测试,似乎对我来说效果很好。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句