Java 中使用 Stream 将 List 转换为 Map 实战笔记(生产级版)

发布于:2025-07-12 ⋅ 阅读:(20) ⋅ 点赞:(0)

Java 中使用 Stream 将 List 转换为 Map 实战笔记(生产级版)

在日常开发中,将 List 转换为 Map 是高频操作(如通过 ID 快速查询对象、按属性分组等)。使用 Stream API 的 Collectors.toMap() 可以优雅实现,但生产环境中需关注键冲突、null 键、Map 实现选择等细节。本文系统梳理核心用法、易错点及最佳实践,帮你写出健壮且高效的代码。

一、基础准备:前提与场景

1. 示例对象定义

下文示例基于 User 类,含常见属性及 getter 方法(生产中建议用 Lombok 简化,@Data 注解会自动生成 getter、equals、hashCode 等方法,减少模板代码):

@Data // Lombok 注解:自动生成 getter/setter/equals/hashCode/toString
public class User {
   
    private Integer id;    // 包装类型,可能为 null(需特别处理)
    private String name;   // 可能为 null
    private int age;       // 基本类型,无 null 问题

    public User(Integer id, String name, int age) {
   
        this.id = id;
        this.name = name;
        this.age = age;
    }
}

2. 核心方法:Collectors.toMap() 签名解析

toMap() 有两个重载方法,需根据场景选择:

// 基础版:仅指定键、值映射(默认用 HashMap,键冲突会抛异常)
toMap(
    Function<? super T, ? extends K> keyMapper,  // 键映射逻辑
    Function<? super T, ? extends U> valueMapper // 值映射逻辑
)

// 完整版:支持键冲突处理 + 指定 Map 实现(生产级场景首选)
toMap(
    Function<? super T, ? extends K> keyMapper,    // 键映射逻辑
    Function<? super T, ? extends U> valueMapper,  // 值映射逻辑
    BinaryOperator<U> mergeFunction,               // 键冲突处理策略
    Supplier<M> mapFactory                         // 指定 Map 实现(如 TreeMap)
)

核心区别:基础版仅适用于「键绝对唯一且无需定制 Map 类型」的场景,生产中更推荐完整版,避免隐藏风险。

二、基础转换:方法引用 vs Lambda 表达式

1. 简单属性映射(最常用场景)

根据映射逻辑的复杂度,可选择更简洁的方法引用或更灵活的 Lambda:

方法引用
  • 适用场景: 映射逻辑简单(直接取属性),代码更简洁

  • Map<Integer, String> userMapByMethodRef = users.stream()
        .collect(Collectors.toMap(User::getId, 

网站公告

今日签到

点亮在社区的每一天
去签到