当前位置: 代码网 > it编程>编程语言>Java > Java8 Collectors.toMap() 的两种用法

Java8 Collectors.toMap() 的两种用法

2025年09月28日 Java 我要评论
一、简单介绍collectors.tomap(): jdk8 中提供,用于将 stream 流转换为 map。用法1:根据某一属性,对对象的实例或属性做映射例如:使用 stream 想要将集合的某一属

一、简单介绍

collectors.tomap(): jdk8 中提供,用于将 stream 流转换为 map。

用法1:根据某一属性,对对象的实例或属性做映射

例如:使用 stream 想要将集合的某一属性(例如手机号)作为 key,对象本身作为 value,这样我们在根据属性获取实例或实例的其他属性时就可以省去遍历每个对象的时间。

// 获取 手机号-userinfo 映射
map<string, userinfo> phonenumbermap = list.stream().collect(collectors.tomap(userinfo::getphonenumber(), function.identity());

用法2:根据某一属性,对对象集合进行去重

原始 jdk8 实现根据某一属性去重:

// 查询数据
list<userinfo> list = userinfomapper.getlist();
// 根据 姓名 去重
list = list.stream().filter(o -> o.getname() != null).collect(
                collectors.collectingandthen(collectors.tocollection(
                    () -> new treeset<>(comparator.comparing(userinfo::getname))), arraylist<aoo>::new));

通过 collectors.tomap() 实现根据某一属性去重:

// 查询数据
list<userinfo> list = userinfomapper.getlist();
// 根据 姓名 去重
map<string, userinfo> collect = list.stream()
    .collect(collectors.tomap(userinfo::getname, o -> o, (v1, v2) -> v1));
list = new arraylist<>(collect.values());

二、duplicate key 异常

1)异常重现:

    public static void main(string[] args) {
        list<user> list = arrays.aslist(
                new user("张三", 15),
                new user("张三", 16));
        // 获取 姓名-年龄 映射
        map<string, integer> namemap = list.stream().collect(collectors.tomap(user::getname, user::getage));
        system.out.println(namemap);
    }
    private static class user {
        private string name;
        private integer age;
        public user(string name, integer age) {
            this.name = name;
            this.age = age;
        }
        public string getname() {
            return name;
        }
        public integer getage() {
            return age;
        }
        @override
        public string tostring() {
            return "user{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }

2)异常截图:

3)异常说明:

​ collectors.tomap() 在 key 重复的时候,是需要指定处理操作的。默认并不会像 hashmap 一样直接对原值进行覆盖。当出现 key 重复但没有指定操作时,就会抛出一个 illegalstateexception 非法声明异常。

4)异常处理:

​ 我们只需要增加第3个参数,指定当 key 重复时需要进行的操作即可:

// 获取 姓名-年龄 映射
// 第3个参数会执行 map.merge() 操作,(v1, v2) -> v1 表示重复时抛弃后面的值
map<string, integer> namemap = list.stream()
    .collect(collectors.tomap(user::getname, user::getage, (v1, v2) -> v1));

​ 运行程序,输出结果如下:

三、collectors.tomap() 导致的空指针异常

1)异常重现:

    public static void main(string[] args) {
        list<user> list = arrays.aslist(
                new user("张三", 15),
                new user("李四", null));
        // 获取 姓名-年龄 映射
        map<string, integer> namemap = list.stream()
            .collect(collectors.tomap(user::getname, user::getage, (v1, v2) -> v1));
        system.out.println(namemap);
    }
    private static class user {
        private string name;
        private integer age;
        public user(string name, integer age) {
            this.name = name;
            this.age = age;
        }
        public string getname() {
            return name;
        }
        public integer getage() {
            return age;
        }
        @override
        public string tostring() {
            return "user{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }

2)异常截图:

3)异常说明:

​ 导致空指针是因为 collectors.tomap() 底层会调用 hashmap.merge() 方法,在执行 merge() 方法的时候会对 value 进行非空判断,从而抛出异常:

4)异常处理:

方法一:替换 null 为一个默认值,比如 -1

// 获取 姓名-年龄 映射
map<string, integer> namemap = list.stream()
    .collect(collectors.tomap(user::getname, o -> optional.ofnullable(o.getage()).orelse(-1), (v1, v2) -> v1));

运行程序,输出结果如下:

方法二:调用 collect() 方法实现

public static void main(string[] args) {
    list<user> list = arrays.aslist(
        new user("张三", 15),
        new user("张三", 16),
        new user("李四", null));
    map<string, integer> namemap = list.stream()
        .collect(hashmap::new, (m, o) -> m.put(o.getname(), userinfo.getage()), hashmap::putall);
    system.out.println(namemap);
}

运行程序,输出结果如下:

四、总结

​ 综合以上两种异常的出现情况和处理方法,考虑到代码的可读性,最终推荐通过如下方式使用 collectors.tomap()

// 获取 姓名-年龄 映射
map<string, integer> namemap = list.stream()
    .collect(collectors.tomap(user::getname, o -> optional.ofnullable(o.getage()).orelse(-1), (v1, v2) -> v1));

参考地址:

1.java 8中collectors.tomap空指针异常源码分析,https://www.jb51.net/program/294861hkb.htm

到此这篇关于java8 collectors.tomap() 的使用的文章就介绍到这了,更多相关java collectors.tomap()使用内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com