如何使用Java8对父子实体进行分组

如何使用Java8对父子实体进行分组,java,java-8,Java,Java 8,我试图将一些实体分组,将孩子放在父母身上 @Entity public class JournalEntry { Integer id; String message; Integer parentId; } 数据传输对象将如下所示 public class JournalDTO { public JournalDTO (Integer id, String message, List<JournalDTO> childEntrie

我试图将一些实体分组,将孩子放在父母身上

@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;
}
公共类日志{
public JournalDTO(整数id、字符串消息、列表子条目){
this.id=id;
this.message=消息;
this.childEntries=childEntries;
}
整数id;
字符串消息;
列出儿童条目;
}
所以我希望最终得到一个列表,它没有父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());
List journalEntries=service.fetchJournalEntries();
List topLevel=journalEntries.stream().filter(e->null==e.getParentId()).collect(toList());
journalEntries.removeAll(顶级);
List journalDTOs=topLevel.stream()
.map(tl->new JournalDTO(tl.getId(),tl.getMessage(),new ArrayList())
.collect(toList());
然后,我按父ID对其余条目进行分组

Map<Integer, List<JournalEntry>> childMap = journalEntries.stream().collect(groupingBy(Integer::getParentId));
Map childMap=journalEntries.stream().collect(groupingBy(Integer::getParentId));

然后我可以遍历这个映射并将childEntities添加到父实体,但这只会给我第二个级别,然后我必须确保没有子实体的子实体等等。。。有更好的方法吗?

这是一个多么有趣的问题。首先,为了简单起见,我定义了一个方法:

private static JournalDTO toDTO(JournalEntry entry) {
    return new JournalDTO(entry.getId(), entry.getMessage(), new ArrayList<>());
}
第一个应该是显而易见的,它包含一个与
JournalEntry
配对的ID

第二个将
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);
}); 
//首先获取那些没有父母的
Set id=map.get(-1);
//这是最终的结果
List all=new ArrayList();
//对于没有父实体的每个实体,开始在地图中搜索
ID.forEach(x->{
JournalDTO parentDTO=toDTO(identity.get(x));
递归(x,map,identity,parentDTO);
全部。添加(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);
        });
    }
}
私有静态无效递归(
整数parentId,
地图,
地图标识,
JournalTo JournalTo){
设置childrenIds=map.get(parentId);
if(childrenIds!=null&&!childrenIds.isEmpty()){
儿童ID.forEach(x->{
JournalDTO childto=toDTO(identity.get(x));
journalDTO.getChildEntries().add(childTo);
递归(x,map,identity,childDTO);
});
}
}

我已经在一个相当简单的案例(带有
==
的案例)中对此进行了测试,似乎对我来说效果不错。

你能用一个例子解释更多吗。我不明白你想做什么?因为你写了一些代码,除了最后一个。这不是真的,因为您为integer键入了getParentId(也修复它)。省略了getter/setters,因此getParentId将返回日记账分录的整数ID。所以基本上我需要日记账DTO的集合,它可以有一个日记账DTO的集合作为子条目属性,每个日记账DTO都可以有一个日记账DTO的集合作为子条目,等等,parentId将条目标识为id等于parentId的条目的子条目。我有一个类似的用例,除了1)我的列表包含重复的记录,即id属性可以在多行中重复,2)列表不包含父项为空的任何记录。虽然我试图自己解决,但任何帮助都将不胜感激。。
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);
        });
    }
}