[英]Group a list of values using java 8
我有以下课程:
public class OrganizationRoleDTO {
private Long organizationId;
private String organizationTitle;
private String roleId;
private String roleTitle;
}
在我的DAO中,我有一个函数将返回OrganizationRoleDTO
的列表,如下所示:
1, "Organization 1", 1, "Role 1"
1, "Organization 1", 2, "Role 2"
2, "Organization 2", 1, "Role 1"
2, "Organization 2", 3, "Role 3"
3, "Organization 3", 3, "Role 3"
我想要做的是使用OrganizationRoleDTO
列表中的上述信息创建一个新列表,因此新列表如下:
1, "Organization 1", [{1, "Role 1"}, {2, "Role 2"}]
1, "Organization 2", [{1, "Role 1"}, {3, "Role 3"}]
1, "Organization 3", [{3, "Role 3"}]
我在这里所做的是,我按字段organizationTitle
对列表进行了分组,并且生成的列表的类型为OrganizationDTO
,其中OrganizationDTO
的定义如下:
public class OrganizationDTO{
private Long id;
private String title;
private List<RoleDTO> rolesList;
}
这是RoleDTO
的定义:
public class RoleDTO {
private String title;
private Long id;
private List<ProfileDTO> profilesList;
}
这是我尝试的代码:
List<OrganizationRoleDTO> organizationRoleList = findOrganizationRoleList();
Map<String, OrganizationDTO> map = organizationRoleList.stream().collect(HashMap::new, (m, t) -> {
m.computeIfAbsent(t.getOrganizationTitle(), x -> new OrganizationDTO(t.getOrganizationId(), t.getOrganizationTitle()))
.getRolesList()
.add(new RoleDTO(t.getRoleId(), t.getRoleTitle(), profileBP.findProfilsByRoleId(t.getRoleId())));
}, (m1, m2) -> {
m2.forEach((k, v) -> {
OrganizationDTO organizationDTO = m1.get(k);
if (organizationDTO != null) {
organizationDTO.getRolesList().addAll(v.getRolesList());
} else {
m1.put(k, v);
}
});
});
List<OrganizationDTO> list = map.values().stream().collect(Collectors.toList());
这段代码按预期工作,唯一的问题是很难读取和调试(明显的可伸缩性问题)。
还有另一种写方法吗?
因此,似乎首先您可能想将其转换为“ organizationId to OrganizationRoleDTO”映射,如下所示:
Map<Long, OrganizationRoleDTO> map = organizationRoleList.stream()
.collect(Collectors.groupingBy(OrganizationRoleDTO::organizationId));
然后,您只需要将每个映射条目转换为OrganizationDTO。
您可以使用CollectingAndThen
做到这一点
List<OrganizationDTO> organizationDTOList = list.stream()
.collect(Collectors.collectingAndThen(Collectors.groupingBy(OrganizationRoleDTO::getOrganizationTitle),
stringListMap -> {
List<OrganizationDTO> organizationDTOS = Lists.newArrayList();
stringListMap.keySet().forEach(item -> {
createListOfOrganizationDTO(stringListMap, organizationDTOS, item);
});
return organizationDTOS;
}));
private void createListOfOrganizationDTO(Map<String, List<OrganizationRoleDTO>> stringListMap, List<OrganizationDTO> organizationDTOS, String item) {
List<OrganizationRoleDTO> organizationRoleDTOS = stringListMap.get(item);
OrganizationDTO organizationDTO = new OrganizationDTO();
//Set organizationDTO id and title field.
List<RoleDTO> roleDTOList = organizationRoleDTOS
.stream()
.map(this::createRoleDTO)
.collect(Collectors.toList());
organizationDTO.setRolesList(roleDTOList);
organizationDTOS.add(organizationDTO);
}
private RoleDTO createRoleDTO(OrganizationRoleDTO organizationRoleDTO) {
RoleDTO roleDTO = new RoleDTO();
roleDTO.setId(organizationRoleDTO.getRoleId());
roleDTO.setTitle(organizationRoleDTO.getRoleTitle());
return roleDTO;
}
但这也不是很好。
我对您的模型进行了一些更改。 我在模型中添加了一些方法,还定义了Function
和BiFunction
进行简化。
BiFunction<OrganizationDTO,OrganizationDTO,OrganizationDTO> function =
(o1,o2)-> new OrganizationDTO(o2.getId(),o2.getTitle())
.setRoleList(Stream.of(o1.getRolesList(),o2.getRolesList())
.flatMap(List::stream).collect(Collectors.toList()));
和Function
Function<List<OrganizationDTO>,OrganizationDTO> dtoFunction =
l->l.stream()
.reduce(new OrganizationDTO(),
(o1,o2)->function.apply(o1,o2));
将这些方法添加到RoleDTO
类中。
public OrganizationDTO addRole(Long id, String title){
this.getRolesList().add(new RoleDTO(title,id));
return this;
}
public OrganizationDTO setRoleList(List<RoleDTO> roleList ){
this.getRolesList().addAll(roleList);
return this;
}
和最终解决方案
List<OrganizationDTO> result = list.stream()
.map(organizationRoleDTO -> new OrganizationDTO(organizationRoleDTO.getOrganizationId(), organizationRoleDTO.getOrganizationTitle())
.addRole(Long.parseLong(organizationRoleDTO.getRoleId()),organizationRoleDTO.getRoleTitle())).collect(Collectors.toList())
.stream()
.collect(Collectors.groupingBy(OrganizationDTO::getTitle))
.values()
.stream()
.map(dtoFunction::apply)
.collect(Collectors.toList());
我认为这应该工作:(配置文件列表替换为空的arraylist)
public Map<String, OrganizationDTO> toOrganizationDTOMap(List<OrganizationRoleDTO> list) {
Map<String, List<OrganizationRoleDTO>> map = list.stream()
.collect(Collectors.groupingBy(OrganizationRoleDTO::getOrganizationTitle));
Map<String, List<OrganizationDTO>> map1 = map.entrySet()
.stream()
.map(e -> new AbstractMap.SimpleImmutableEntry<>(e.getKey(), toOrganizationDTO(e)))
.collect(Collectors.toMap(AbstractMap.SimpleImmutableEntry::getKey, AbstractMap.SimpleImmutableEntry::getValue));
return map1;
}
private List<OrganizationDTO> toOrganizationDTO(Map.Entry<String, List<OrganizationRoleDTO>> e) {
return e.getValue().stream().map(o -> new OrganizationDTO(o.getOrganizationId(), o.getOrganizationTitle(),
e.getValue().stream().map(ob -> new RoleDTO(ob.getRoleTitle(), ob.getRoleId(), new ArrayList<>()))
.collect(Collectors.toList())))
.distinct()
.collect(Collectors.toList());
}
您要做的是将原始列表reduce
为紧凑的项目。
Map<String, OrganizationDTO> map = organizationRoleList.stream()
.collect(groupingBy(OrganizationRoleDTO::getOrganizationTitle,
mapping(OrganizationDTO::of,
reducing(new OrganizationDTO(), OrganizationDTO::add))));
为了支持reduce,您应该在OrganizationDTO
类中添加一些方法:
@Data
public static class OrganizationDTO {
private Long id;
private String title;
private List<RoleDTO> rolesList;
public OrganizationDTO() {
}
public static OrganizationDTO of(OrganizationRoleDTO source) {
OrganizationDTO newOrganization = new OrganizationDTO();
newOrganization.setId(source.getOrganizationId());
newOrganization.setTitle(source.getOrganizationTitle());
List<RoleDTO> rolesList = new ArrayList<>();
rolesList.add(new RoleDTO(source.getRoleTitle(), Long.parseLong(source.getRoleId())));
newOrganization.setRolesList(rolesList);
return newOrganization;
}
public OrganizationDTO add(OrganizationDTO other) {
if (id.equals(other.getId())) {
return this;
}
rolesList.addAll(other.getRolesList());
return this;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.