Java8 Collectors.toMap() 的两种用法

 更新时间:2025年09月28日 10:21:46   作者:不愿放下技术的小赵  
Collectors.toMap():JDK8 中提供,用于将Stream流转换为 Map,本文给大家介绍Java8 Collectors.toMap() 的两种用法,感兴趣的朋友一起看看吧

一、简单介绍

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()使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java设计模式之策略模式在促销活动场景中的使用案例

    java设计模式之策略模式在促销活动场景中的使用案例

    这篇文章主要为大家介绍了java设计模式之策略模式在促销活动场景中案例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-05-05
  • java的equals和==的比较示例

    java的equals和==的比较示例

    这篇文章主要介绍了java的equals和==的比较示例,需要的朋友可以参考下
    2014-04-04
  • SpringBoot集成Spring security JWT实现接口权限认证

    SpringBoot集成Spring security JWT实现接口权限认证

    这篇文章主要介绍了SpringBoot集成Spring security JWT实现接口权限认证,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • Spring Boot学习入门之统一异常处理详解

    Spring Boot学习入门之统一异常处理详解

    我们在做Web应用的时候,请求处理过程中发生错误是非常常见的情况。下面这篇文章主要给大家介绍了关于Spring Boot学习入门之统一异常处理的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下。
    2017-09-09
  • jstack配合top命令分析CPU飙高、程序死锁问题

    jstack配合top命令分析CPU飙高、程序死锁问题

    记得前段时间,同事说他们测试环境的服务器cpu使用率一直处于100%,本地又没有什么接口调用,为什么会这样?cpu使用率居高不下,自然是有某些线程一直占用着cpu资源,那又如何查看占用cpu较高的线程
    2021-09-09
  • springboot配置ssl后启动一直是端口被占用的解决

    springboot配置ssl后启动一直是端口被占用的解决

    这篇文章主要介绍了springboot配置ssl后启动一直是端口被占用的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • java字节流知识点总结

    java字节流知识点总结

    在本篇文章里小编给大家分享的是关于java字节流的相关知识点内容,有兴趣的朋友们跟着学习参考下。
    2019-07-07
  • 关于Nacos单机启动的两种方式

    关于Nacos单机启动的两种方式

    这篇文章主要介绍了关于Nacos单机启动的两种方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • Java 的访问修饰符public,protected,private(封装、继承)

    Java 的访问修饰符public,protected,private(封装、继承)

    这篇文章主要介绍了Java 的访问修饰符public,protected,private(封装、继承),文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-09-09
  • tomcat部署java web项目遇到的问题及解决方法

    tomcat部署java web项目遇到的问题及解决方法

    这篇文章主要介绍了tomcat部署java web项目遇到的问题及解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-07-07

最新评论