英文:
Group By in java 8 with multiple levels of grouping
问题
我有这样的结构
| 主管1 | 经理1 | 员工1 |
| 主管1 | 经理1 | 员工2 |
| 主管1 | 经理2 | 员工3 |
| 主管2 | 经理3 | 员工4 |
我从数据库中提取这些数据到一个POJO(Plain Old Java Object)中,就像这样
@Data
public class Workers {
private String directorName;
private String managerName;
private String employeeName;
}
数据库是非规范化的。
现在在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;
...
}
通过分组,我想要得到List<WorkersResponse>
。目前,我已经找出了如何对主管进行分组:
Map<WorkersResponse, List<Workers>> collect = all.stream()
.collect(Collectors.groupingBy(v -> {
WorkersResponse workersResponse= new WorkersResponse();
workersResponse.setDirector(v.getDirectorName());
return workersResponse;
}));
但是,我应该如何填充带有经理和员工的列表呢?
英文:
I have such structure
| Director1 | Manager1 | Employee1 |
| Director1 | Manager1 | Employee2 |
| Director1 | Manager2 | Employee3 |
| Director2 | Manager3 | Employee4 |
I fetch this data from Db to Pojo like this
@Data
public class Workers {
private String directorName;
private String managerName;
private String employeeName;
}
DB is denormalized.
Mow in java code I need to group this response to not to return redundant data. My response data looks like
@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;
...
}
With grouping I want to receive List<WorkersResponse>. For now I figured out how to group directors :
Map<WorkersResponse, List<Workers >> collect = all.stream()
.collect(Collectors.groupingBy(v -> {
WorkersResponse workersResponse= new WorkersResponse();
workersResponse.setDirector(v.getDirectorName());
return workersResponse;
}));
But how should then I populate list with Managers and Employees?
答案1
得分: 2
根据分组要求,您应该尝试使用嵌套分组以及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(), // 导演姓名
e.getValue().entrySet()
.stream()
.map(ie -> new Manager(ie.getKey(), // 经理姓名
ie.getValue()
.stream()
.map(Employee::new)
.collect(Collectors.toList())))
.collect(Collectors.toList())))
.collect(Collectors.toList());
英文:
Based on the grouping requirement, you should try using nested grouping along with Collectors.mapping
such as:
Map<String, Map<String, List<String>>> groupingRequirement = workersList.stream()
.collect(Collectors.groupingBy(Workers::getDirectorName,
Collectors.groupingBy(Workers::getManagerName,
Collectors.mapping(Workers::getEmployeeName,
Collectors.toList()))));
Thereafter mapping to objects of the desired type is the only constraint left while you iterated over the entries of the collected 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());
答案2
得分: 1
@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())));
英文:
@Naman already given the better answer, just want to add,
you can get WorkersResponse
in this way also using 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())));
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论