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<User> 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<Integer, User> 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<Integer, String> 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<String, User> 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<Integer, String> 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<String, User> 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<String, List<String>> collect = users.stream().
                //User对象的edu属性作为key,但是会存在key相同的情况
                        collect(Collectors.toMap(User::getEdu,
                        //value的值,是集合的结构
                        p -> {
                            //获取value值
                            List<String> users = new ArrayList<>();
                            users.add(p.getUserName());
                            return users;
                        },
                        //集合合并
                        (List<String> k1, List<String> 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<String, Integer> 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<String, List<User>> collect = users.stream().
                        collect(Collectors.groupingBy(User::getEdu));
        System.out.println(collect);
    }

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

    public static void main(String[] args) {
        Map<String, List<String>> 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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,496评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,407评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,632评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,180评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,198评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,165评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,052评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,910评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,324评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,542评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,711评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,424评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,017评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,668评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,823评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,722评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,611评论 2 353

推荐阅读更多精彩内容