繁体   English   中英

使用Java 8对值列表进行分组

[英]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;
  }

但这也不是很好。

我对您的模型进行了一些更改。 我在模型中添加了一些方法,还定义了FunctionBiFunction进行简化。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM