我有一个课程如下:
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());
此代码按预期工作,唯一的问题是难以阅读和调试(明显的可伸缩性问题)。
还有其他方法可以写这个吗?
答案 0 :(得分:0)
所以,似乎首先你可能想把它转换为&#34; organizationId到OrganizationRoleDTO&#34;像这样的地图:
Map<Long, OrganizationRoleDTO> map = organizationRoleList.stream()
.collect(Collectors.groupingBy(OrganizationRoleDTO::organizationId));
然后你只需要将每个地图条目转换为OrganizationDTO。
答案 1 :(得分:0)
你可以使用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;
}
但这也不是很好。
答案 2 :(得分:0)
我在你的模型中做了一些改变。我在模型中添加了一些方法,并定义了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());
答案 3 :(得分:0)
我认为这应该有效:(配置文件列表被替换为空的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());
}
答案 4 :(得分:0)
您要做的是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;
}
}