【问题标题】:Group By in java 8 with multiple levels of groupingjava 8中的Group By,具有多级分组
【发布时间】:2020-05-29 12:29:38
【问题描述】:

我有这样的结构

| Director1 | Manager1 | Employee1 |
| Director1 | Manager1 | Employee2 |
| Director1 | Manager2 | Employee3 |
| Director2 | Manager3 | Employee4 |

我像这样从 Db 获取这些数据到 Pojo

@Data
public class Workers {
 private String directorName;
 private String managerName;
 private String employeeName;
}

DB 是非规范化的。

在 java 代码中我需要将此响应分组以不返回冗余数据。我的响应数据看起来像

@Data
public class WorkersResponse{
 private String directorName;
 ...
 private List<Manager> managers;
}

@Data
public class Manager{
 private String manager;
  ...
 private List<Employee> employee;
}

@Data
public class Employee{
 private String employee;
 ...
}

通过分组我想接收列表。现在我想出了如何将导演分组:

Map<WorkersResponse, List<Workers >> collect = all.stream()
            .collect(Collectors.groupingBy(v -> {
                WorkersResponse workersResponse= new WorkersResponse();
                workersResponse.setDirector(v.getDirectorName());
                return workersResponse;
            }));

但是我应该如何用经理和员工填充列表呢?

【问题讨论】:

  • 你只需要名字吗?

标签: java java-stream grouping


【解决方案1】:

根据分组要求,您应该尝试使用嵌套分组以及Collectors.mapping,例如:

Map<String, Map<String, List<String>>> groupingRequirement = workersList.stream()
        .collect(Collectors.groupingBy(Workers::getDirectorName,
                Collectors.groupingBy(Workers::getManagerName,
                        Collectors.mapping(Workers::getEmployeeName,
                                Collectors.toList()))));

此后,当您迭代收集的 Map 的条目时,映射到所需类型的对象是唯一的约束 -

List<WorkersResponse> workersResponses = groupingRequirement.entrySet().stream()
        .map(e -> new WorkersResponse(e.getKey(), // director name
                e.getValue().entrySet()
                        .stream()
                        .map(ie -> new Manager(ie.getKey(), // manager name
                                ie.getValue()
                                        .stream()
                                        .map(Employee::new)
                                        .collect(Collectors.toList())))
                        .collect(Collectors.toList())))
        .collect(Collectors.toList());

【讨论】:

  • 映射时也可以创建Employee
  • @Eklavya 没错,现在我看到另一个答案适应了它,进一步编辑这个答案没有多大意义。无论如何,嵌套分组的方法对于解决方案至关重要。
  • @Naman 也许你现在可以更新它。我删除了另一个。
  • @Naman 我添加了一个答案,像你的解决方案一样收集和映射,希望你没问题。
  • @Naman 非常感谢。在您发布答案之前,我想出了第一部分,但第二部分对我有很大帮助。是的,我已经将它链接到第二个答案中。谢谢
【解决方案2】:

@Naman 已经给出了更好的答案,只是想补充一下, 你可以通过这种方式获得WorkersResponse,也可以使用collectingAndThen

List<WorkersResponse> requirement = workersList.stream()
        .collect(Collectors.collectingAndThen(Collectors.groupingBy(Workers::getDirectorName,
                Collectors.collectingAndThen(Collectors.groupingBy(Workers::getManagerName,
                        Collectors.mapping(w -> new Employee(w.getEmployeeName()),Collectors.toList())),
                    e -> e.entrySet().stream().map(ie -> new Manager(ie.getKey(), ie.getValue()))
                          .collect(Collectors.toList()))),
            e -> e.entrySet().stream().map(ie -> new WorkersResponse(ie.getKey(), ie.getValue()))
                          .collect(Collectors.toList())));

【讨论】:

    猜你喜欢
    • 2018-01-10
    • 2022-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多