JDK8中List转换为Map

JDK1.8为集合提供了Stream流,可以快速的将List集合转换为Map集合。

1. 数据准备:

public class Test {
     //数据准备 
    @Data
    public static class User {
        private Integer id;
        private Integer schoolId;
        private String userName;
        private String edu;
    }

    static private List users = new ArrayList<>();

    static {
        User u1 = new User();
        u1.setId(1001);
        u1.setSchoolId(100);
        u1.setUserName("小1");
        u1.setEdu("001");

        User u2 = new User();
        u2.setId(1002);
        u2.setSchoolId(100);
        u2.setUserName("小2");
        u2.setEdu("002");

        User u3 = new User();
        u3.setId(2010);
        u3.setSchoolId(200);
        u3.setUserName("小3");
        u3.setEdu("001");

        User u4 = new User();
        u4.setId(3001);
        u4.setSchoolId(300);
        u4.setEdu("003");
        users.add(u1);
        users.add(u2);
        users.add(u3);
        users.add(u4);
    }
}

2. 使用方法:

  • 若是以User对象的id属性作为key,User对象为value。转换成的一个Map。
    public static void main(String[] args) {
        //将List转换为Map
        Map userMap = users.stream().collect(Collectors.toMap(User::getId,
                Function.identity()));

        System.out.println(JSON.toJSONString(userMap));

    }

效果一览:

null:{"edu":"004","schoolId":400,"userName":"小5"},
3001:{"edu":"003","id":3001,"schoolId":300,"userName":"小4"},
1001:{"edu":"001","id":1001,"schoolId":100,"userName":"小1"},
2010:{"edu":"001","id":2010,"schoolId":200,"userName":"小3"},
1002:{"edu":"002","id":1002,"schoolId":100,"userName":"小2"}
}
  • 若是将对象的某个属性作为key,某个属性作为value。转换成一个Map。
    public static void main(String[] args) {
        //将List转换为Map
        Map stringMap = users.stream().
                collect(Collectors.toMap(User::getId,
                        User::getEdu));
        System.out.println(JSON.toJSONString(stringMap));
    }

3. 存在的问题

  1. key相同的情况
    public static void main(String[] args) {
        //将List转换为Map
        Map userMap = users.stream().
                //User对象的edu属性作为key,但是会存在key相同的情况
                collect(Collectors.toMap(User::getEdu,
                        Function.identity()));
        System.out.println(JSON.toJSONString(userMap));
    }

出现异常:重复秘钥

Exception in thread "main" java.lang.IllegalStateException: Duplicate key 
  1. value为null的情况
    public static void main(String[] args) {
        //将List转换为Map
        Map stringMap = users.stream().
                //User对象的edu属性作为key,但是会存在key相同的情况
                        collect(Collectors.toMap(User::getId, User::getUserName));
        System.out.println(JSON.toJSONString(stringMap));
    }

出现异常:空指针异常

Exception in thread "main" java.lang.NullPointerException

4. 解决方案

JDK8的Collectors.toMap()提供了第三个参数,来处理上面的问题。

  1. 当出现重复的key问题时:合并value值。
    public static void main(String[] args) {
        //将List转换为Map,解决key冲突的问题。
        Map userMap = users.stream().
                //User对象的edu属性作为key,但是会存在key相同的情况
                        collect(Collectors.toMap(User::getEdu,
                        //value的值
                        Function.identity(),
                        //合并两个value值:k1是旧值,k2是新值。
                        (k1, k2) -> {
                            log.info(JSON.toJSONString(k1));
                            log.info(JSON.toJSONString(k2));
                            return k2;
                        }));
        System.out.println(userMap);
    }
  1. 当出现value为null的情况:
    public static void main(String[] args) {
        //将List转换为Map,解决key冲突的问题。
        Map> collect = users.stream().
                //User对象的edu属性作为key,但是会存在key相同的情况
                        collect(Collectors.toMap(User::getEdu,
                        //value的值,是集合的结构
                        p -> {
                            //获取value值
                            List users = new ArrayList<>();
                            users.add(p.getUserName());
                            return users;
                        },
                        //集合合并
                        (List k1, List k2) -> {
                            k1.addAll(k2);
                            return k1;
                        }));
        System.out.println(collect);
    }

得到的集合:

{001=[小1, 小3, null], 002=[小2]}

5. 扩展

  1. 转换为TreeMap:
    public static void main(String[] args) {
        //将List转换为Map,解决key冲突的问题。
        TreeMap collect = users.stream().
                //User对象的edu属性作为key,但是会存在key相同的情况
                        collect(Collectors.toMap(User::getEdu,
                        //value的值,是集合的结构
                        User::getId,
                        (k1, k2) -> k1, TreeMap::new
                ));
        System.out.println(collect);
    }
  1. 对List进行分组:
    public static void main(String[] args) {
        Map> collect = users.stream().
                        collect(Collectors.groupingBy(User::getEdu));
        System.out.println(collect);
    }

若是想得到的value是某个值,可以使用mapping来进行映射:

    public static void main(String[] args) {
        Map> collect = users.stream().
                collect(Collectors.groupingBy(User::getEdu,
                        Collectors.mapping(User::getUserName, Collectors.toList())));
        System.out.println(collect);
    }

若是Map中key对应的是一个List集合,那么可以使用group by来实现
推荐阅读:JDK8对List进行分组操作(stream的groupby)

推荐阅读

List转换为TreeMap

List转换为HashMap的注意事项

Java8函数式编程(三):Collectors.groupingBy

你可能感兴趣的:(JDK8中List转换为Map)