致远啊 发表于 2022-11-15 14:12

java两个集合合并问题

本帖最后由 致远啊 于 2022-11-15 17:42 编辑

有两个SysRoleAuth的List集合

- 一个集合只有roleId、perms数据(可能有多个重复roleId,perms不重复)
- 另一个只有roleId、resourceCode数据

两个集合roleId并不是都一一对应的

问:

如何把两集合相同roleId数据合并添加

若有不同roleId,也添加进去

最后类型为: `Map<Long, SysRoleList>`

> 画了个图,方便大家理解

!(https://api.oddfar.com/img/1231.png)



```java
@Data
@AllArgsConstructor
@NoArgsConstructor
public class SysRoleAuth {

    /**
   * 角色id
   */
    Long roleId;

    /**
   * 权限字符
   */
    String perms;

    /**
   * 资源编码
   */
   String resourceCode;
}
```

SysRoleList:

```java
@Data
@AllArgsConstructor
@NoArgsConstructor
public class SysRoleList {

    /**
   * 角色id
   */
    Long roleID;

    /**
   * 权限字符
   */
    Set<String> perms;

    /**
   * 资源编码
   */
    Set<String> resourceCode;
}
```



这是我写的代码,只是实现功能,**有没有好的解决方案**

```java
package com.oddfar.test.role;

import java.util.*;
import java.util.stream.Collectors;

public class TestList {

    public static void main(String[] args) {
      Map<Long, SysRoleList> resMap = new HashMap<>();

      Map<Long, List<SysRoleAuth>> list1 = creatList1().stream().collect(Collectors.groupingBy(SysRoleAuth::getRoleID));


      for (Long roleId : list1.keySet()) {

            List<SysRoleAuth> list = list1.get(roleId);
            //把关于roleId的perms数据建立成set集合
            Set<String> perms = new HashSet<>();
            list.stream().forEach(r -> perms.add(r.getPerms()));

            //如果resMap包含roleId
            if (resMap.containsKey(roleId)) {
                SysRoleList sysRoleList = resMap.get(roleId);
                if (sysRoleList.getPerms() != null) {
                  //如果存在perms,则添加数据
                  sysRoleList.getPerms().addAll(perms);
                } else {
                  //无数据则直接set
                  sysRoleList.setPerms(perms);
                }
            } else {
                //不包含roleId重新生成
                SysRoleList sysRoleList = new SysRoleList(roleId, perms, null);
                resMap.put(roleId, sysRoleList);
            }

      }

      //list2集合操作同理list1
      Map<Long, List<SysRoleAuth>> list2 = creatList2().stream().collect(Collectors.groupingBy(SysRoleAuth::getRoleID));

      for (Long roleId : list2.keySet()) {
            List<SysRoleAuth> list = list2.get(roleId);
            //把关于roleId的resource数据建立成set集合
            Set<String> resourceSet = new HashSet<>();
            list.stream().forEach(r -> resourceSet.add(r.getResourceCode()));

            //如果map包含roleId
            if (resMap.containsKey(roleId)) {
                SysRoleList sysRoleList = resMap.get(roleId);
                if (sysRoleList.getResourceCode() != null) {
                  sysRoleList.getResourceCode().addAll(resourceSet);
                } else {
                  sysRoleList.setResourceCode(resourceSet);
                }

            } else {
                SysRoleList sysRoleList = new SysRoleList(roleId, null, resourceSet);
                resMap.put(roleId, sysRoleList);
            }

      }
      System.out.println(resMap);


    }

    /**
   * 创建第1个集合
   */
    public static List<SysRoleAuth> creatList1() {
      List<SysRoleAuth> list = new ArrayList<>();
      //id为1的权限字符列表
      list.add(new SysRoleAuth(1L, "system:user:list", null));
      list.add(new SysRoleAuth(1L, "system:user:add", null));
      list.add(new SysRoleAuth(1L, "system:user:edit", null));
      //id为2的权限字符列表
      list.add(new SysRoleAuth(2L, "system:config:query", null));
      //id为3的权限字符列表
      list.add(new SysRoleAuth(3L, "system:notice:query", null));

      return list;
    }

    /**
   * 创建第2个集合
   */
    public static List<SysRoleAuth> creatList2() {

      List<SysRoleAuth> list = new ArrayList<>();
      //id为1的资源编码列表
      list.add(new SysRoleAuth(1L, null, "campus.test.test1"));
      list.add(new SysRoleAuth(1L, null, "campus.test.test2"));
      //id为2的资源编码列表
      list.add(new SysRoleAuth(2L, null, "campus.test.test1"));
      //id为6的资源编码列表
      list.add(new SysRoleAuth(6L, null, "campus.test.test1"));

      return list;
    }
}
```



最后返回数据:

```
{1=SysRoleList(roleID=1, perms=, resourceCode=), 2=SysRoleList(roleID=2, perms=, resourceCode=), 3=SysRoleList(roleID=3, perms=, resourceCode=null), 6=SysRoleList(roleID=6, perms=null, resourceCode=)}
```

鬼面书生 发表于 2022-11-15 14:26

你就是map里存多个list集合吧?

致远啊 发表于 2022-11-15 14:36

鬼面书生 发表于 2022-11-15 14:26
你就是map里存多个list集合吧?

是的,根据roleId分组

parker.smith 发表于 2022-11-15 15:17

Java8为Map接口新增的merge默认方法可以处理这个问题

mihok 发表于 2022-11-15 16:17

可以搜索下java8 list对象合并 应该能搜索答案, list.stream().map 取对象里的属性,可以加过滤条件也行,然后在转自己想要的格式,也可以用个中间类,存放共同属性的内容,也可以是 A+B = C( 好像就是这个SysRoleList)的全 类,然后把A 集合和B集合数据往C丢,最后根据某个元素进行去重,生成新的list对象

MerlinFenrir 发表于 2022-11-15 16:21

不妨试试用 List.stream().collect(Collectors.groupingBy()) 按照ID分组把所有权限和资源标识都抓出来然后重新生成数据(这样做的话内存开销可能会稍微大一点)

落克 发表于 2022-11-15 20:04

你是不是想合并两个角色共有的权限

致远啊 发表于 2022-11-15 22:43

落克 发表于 2022-11-15 20:04
你是不是想合并两个角色共有的权限

共有的合并,不共有的也添加进去
最后类型为: Map<Long, SysRoleList>
Long是roleId
------
SysRoleList里面有set的权限集合,分别是perms和resource的set集合

鬼面书生 发表于 2022-11-16 09:33

致远啊 发表于 2022-11-15 14:36
是的,根据roleId分组

用数据库吧,list无法分组,你存什么取什么。
数据库分组查询,将结果集存到list就好了。
页: [1]
查看完整版本: java两个集合合并问题