Java Stream API 映射操作:从列表到 Map 的优雅转换!!!

Java Stream API 映射操作:从列表到 Map 的优雅转换

在 Java 8 中,Stream API(Stream Application Programming Interface,流式处理应用程序接口) 引入了强大的函数式编程特性,其中 映射(map) 操作是核心功能之一。通过映射,我们可以将集合中的元素转换为新的形式或结构。本文围绕以下代码,深入探讨映射操作的原理、应用和最佳实践,带你解锁 Java 流式处理的魅力!

Map<String, PaymentRecord> finalResultsMap = paymentRecordRepository
                .findAllByConsignmentSettlementIdAndAdminId(consignmentSettlementId, adminId)
                .stream()
                .collect(Collectors.toMap(PaymentRecord::getOrderNo, pr -> pr, (pr1, pr2) -> pr1));

我们将通过表格总结、Mermaid 流程图、时序图和思维导图,结合代码分析,全面解析映射操作!


表格总结:映射操作核心概念

概念 英文全称 中文全称 描述 代码中的体现
Stream API Stream Application Programming Interface 流式处理应用程序接口 声明式处理集合,支持映射等操作 .stream() 将列表转为流
映射(map) Mapping Operation 映射操作 将流元素转换为新值或结构 Collectors.toMapPaymentRecord 映射为 Map
Collectors.toMap Collectors to Map 收集器转映射 收集流元素为 Map,指定键和值 toMap(PaymentRecord::getOrderNo, pr -> pr, ...) 生成键值对
方法引用 Method Reference 方法引用 简化键映射的语法糖 PaymentRecord::getOrderNo 提取键
Lambda 表达式 Lambda Expression Lambda 表达式 定义值映射和合并逻辑 pr -> pr(pr1, pr2) -> pr1

映射操作详解

1. 什么是映射操作?

  • 定义:映射(Mapping Operation,映射操作)是 Stream API 中的一种中间操作(或通过收集器实现),通过函数将流中的每个元素转换为另一个值或结构。常见的映射操作包括:
    • .map(...):将元素转换为新值(例如,将对象映射为某个字段)。
    • .collect(Collectors.toMap(...)):将元素映射为键值对,收集到 Map
  • 代码中的体现
    .collect(Collectors.toMap(PaymentRecord::getOrderNo, pr -> pr, (pr1, pr2) -> pr1))
    
    这里使用 Collectors.toMapPaymentRecord 流映射为 Map,其中:
    • PaymentRecord::getOrderNo 提取 orderNo(字符串)。
    • pr -> pr 保留整个 PaymentRecord 对象。
    • 合并函数(pr1, pr2) -> pr1 处理键冲突。
  • 作用:将数据库查询结果(List)映射为以 orderNo 为键的 Map,便于快速查找。

2. 代码分析:映射的实现 ️

  • 步骤分解
    1. 查询数据库paymentRecordRepository.findAllByConsignmentSettlementIdAndAdminId 返回 List
    2. 转换为流.stream() 将列表转为 Stream
    3. 映射到 MapCollectors.toMap 执行映射操作:
      • 键映射PaymentRecord::getOrderNo,提取 orderNo 作为键。
      • 值映射pr -> pr,将整个 PaymentRecord 作为值。
      • 合并逻辑(pr1, pr2) -> pr1,若 orderNo 重复,保留第一个记录。
  • 输出示例
    假设数据库返回:
    • PaymentRecord(orderNo="CON20250521-001", id=1)
    • PaymentRecord(orderNo="CON20250521-002", id=2)
      结果为:
    {
      "CON20250521-001": PaymentRecord(id=1),
      "CON20250521-002": PaymentRecord(id=2)
    }
    

3. 映射中的关键技术

  • 方法引用(Method Reference,方法引用)
    • PaymentRecord::getOrderNo 是实例方法引用,等价于 pr -> pr.getOrderNo(),用于提取键。
    • 提高代码简洁性和可读性。
  • Lambda 表达式(Lambda Expression,Lambda 表达式)
    • pr -> pr:值映射函数,返回 PaymentRecord 本身。
    • (pr1, pr2) -> pr1:合并函数,处理 orderNo 重复情况。
    • 提供灵活的函数式编程方式。️
  • Stream API
    • 提供流式处理框架,支持映射操作。
    • .stream() 是映射的前提,.collect 是映射的终止操作。

Mermaid 流程图:映射操作流程

以下是映射操作的 Mermaid 流程图,所有文本用双引号包裹:

开始
查询数据库获取 List
调用 .stream() 转换为 Stream
调用 .collect(Collectors.toMap)
使用 PaymentRecord::getOrderNo 映射键
使用 pr -> pr 映射值
使用 (pr1, pr2) -> pr1 处理键冲突
生成 Map
结束

说明

  • 查询:从数据库获取 PaymentRecord 列表。
  • 流转换:通过 stream() 进入函数式处理。
  • 映射toMap 将流元素映射为键值对,生成 Map。✨

⏳ 时序图:映射操作交互

以下是时序图,展示映射操作的交互过程,文本不加双引号:

调用者 PaymentRecordService PaymentRecordRepository Stream Collectors 调用 getAndProcessPaymentRecordsBySettlementId findAllByConsignmentSettlementIdAndAdminId 返回 List 调用 stream() 返回 Stream 调用 collect(Collectors.toMap) 使用 PaymentRecord::getOrderNo 映射键 使用 pr ->> pr 映射值 使用 (pr1, pr2) ->> pr1 处理键冲突 返回 Map 返回 finalResultsMap 调用者 PaymentRecordService PaymentRecordRepository Stream Collectors

说明

  • 调用者:触发业务逻辑,通常是控制器。
  • PaymentRecordService:执行查询和映射操作。
  • Stream 和 Collectors:完成流处理和映射到 Map

思维导图:映射操作知识点

以下是 Markdown 格式的思维导图,整理映射相关内容:

Java Stream API 映射操作:从列表到 Map 的优雅转换!!!_第1张图片


⚠️ 注意事项

  1. 空值处理

    • 如果 PaymentRecord.getOrderNo() 返回 nulltoMap 可能抛出 NPE(Null Pointer Exception,空指针异常)。可通过过滤解决:
      .filter(pr -> pr.getOrderNo() != null)
      .collect(Collectors.toMap(PaymentRecord::getOrderNo, pr -> pr, (pr1, pr2) -> pr1));
      
  2. 键冲突

    • 合并函数 (pr1, pr2) -> pr1 假设 orderNo 唯一。若业务允许重复键,需自定义合并逻辑(如合并字段值)。️
  3. 性能

    • Collectors.toMap 生成的默认 HashMap 提供 O(1) 查找效率,适合快速定位记录。
    • 对于大数据集,Stream 操作可能增加内存开销,需谨慎使用。⚡
  4. 扩展性

    • 可结合其他 Stream 操作增强映射功能,例如:
      .stream()
      .map(pr -> new SimpleRecord(pr.getOrderNo(), pr.getTotalAmount()))
      .collect(Collectors.toMap(SimpleRecord::getOrderNo, sr -> sr, (sr1, sr2) -> sr1));
      
      这将 PaymentRecord 映射为简化的 SimpleRecord 对象。

总结

通过分析代码 Map finalResultsMap = ...,我们深入探讨了 映射(Mapping Operation,映射操作) 在 Stream API 中的应用。Collectors.toMap 结合方法引用和 Lambda 表达式,将 PaymentRecord 列表优雅地映射为 Map,展现了 Java 8 函数式编程的简洁与强大。希望本文的表格、流程图、时序图和思维导图能帮助你掌握映射操作的精髓!

有疑问欢迎留言讨论!

你可能感兴趣的:(#,Stream,java)