集合篇1:Stream流方式将List转为Map

3,714 阅读2分钟

在Stream流中将List转换为Map,是使用Collectors.toMap方法来进行转换。

  1. key和value都是对象中的某个属性值

    Map<String, String> userMap = userList.stream().collect(Collectors.toMap(User::getId, User::getName));
    

    说明:userMap为转换后的Map变量,userList要进行转换的对象集合,User::getId为要作为Map键的对象属性,User::getName为要作为Map值的对象属性

  2. key是对象中的某个属性值,value是对象本身(使用返回本身的lambda表达式)

    Map<String, User> userMap = userList.stream().collect(Collectors.toMap(User::getId, User -> User));
    

    说明:User -> User :使用lambda实例化对象本身

  3. key是对象中的某个属性值,value是对象本身(使用Function接口的简洁写法)

    Map<String, User> userMap = userList.stream().collect(Collectors.toMap(User::getId, Function.identity()));
    

    说明:identity():Function接口的一个静态方法,返回一个输出跟输入一样的Lambda表达式对象,等价于形如t -> t形式的Lambda表达式

  4. 使用Collectors.toMap时,抛出的Duplicate key问题

    分析:Duplicate key 即“重复键”,因为Map中key是唯一的,此时Collectors中的toMap方法不清楚取前值还是后值,故抛出异常

    解决方案:

    1. 保证List转Map时,key唯一(不推荐,代码问题不可使用业务去保证唯一)

    2. 使用后一个key的值覆盖前一个key的值

      Map<String, User> userMap = userList.stream().collect(Collectors.toMap(User::getId, Function.identity(), (oldValue, newValue) -> newValue));
      

      说明:Function.identity()指定Map的Value值为对象本身,(oldValue, newValue) -> newValue)即当key冲突是,将前一个key对应的对象本身的value,用后一个key的对象本身的value覆盖掉,即结果为形象为(key1,value2),(key2,value2)

    3. 不进行覆盖,前一个与后一个重复时,key2取key1的value

      Map<String, User> userMap = userList.stream().collect(Collectors.toMap(User::getId, Function.identity(), (oldValue, newValue) -> oldValue));
      

      说明:(oldValue, newValue) -> oldValue)即当key冲突时,取前一个key的对象本身的value为将后一个key对应的对象本身的value,即结果为形象为(key1,value1),(key2,value1)

    4. 保留相同key彼此的值

      Map<String, List<User>> map = userList.stream().collect(Collectors.toMap(User::getId,
                      User -> {
                          List<User> userArrayList = new ArrayList<>();
                          userArrayList.add(User);
                          return userArrayList;
                      },
                      (List<User> oldList, List<User> newList) -> {
                          oldList.addAll(newList);
                          return oldList;
                      }
              ));
      

      说明:保留相同key的不同value时,需要将List转为一个value为集合的Map,通过在lambda表达式的方法体中定义一个新的集合userArrayList来处理key相同时对User对象的添加,并将封装形同key的不同value的集合返回作为Map的value,转换的map测试结果为:{1=[User{id='1', name='hello'}, User{id='1', name='world'}], 2=[User{id='2', name='hello world'}]}