在Java 8中使用多层分组的Group By功能。

huangapple go评论65阅读模式
英文:

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&lt;Manager&gt; managers;
}

@Data
public class Manager{
 private String manager;
  ...
 private List&lt;Employee&gt; 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&lt;WorkersResponse, List&lt;Workers &gt;&gt; collect = all.stream()
			.collect(Collectors.groupingBy(v -&gt; {
				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&lt;String, Map&lt;String, List&lt;String&gt;&gt;&gt; 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&lt;WorkersResponse&gt; workersResponses = groupingRequirement.entrySet().stream()
        .map(e -&gt; new WorkersResponse(e.getKey(), // director name
                e.getValue().entrySet()
                        .stream()
                        .map(ie -&gt; 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&lt;WorkersResponse&gt; requirement = workersList.stream()
        .collect(Collectors.collectingAndThen(Collectors.groupingBy(Workers::getDirectorName,
                Collectors.collectingAndThen(Collectors.groupingBy(Workers::getManagerName,
                        Collectors.mapping(w -&gt; new Employee(w.getEmployeeName()),Collectors.toList())),
                    e -&gt; e.entrySet().stream().map(ie -&gt; new Manager(ie.getKey(), ie.getValue()))
                          .collect(Collectors.toList()))),
            e -&gt; e.entrySet().stream().map(ie -&gt; new WorkersResponse(ie.getKey(), ie.getValue()))
                          .collect(Collectors.toList())));

huangapple
  • 本文由 发表于 2020年5月29日 20:29:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/62086030.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定