当前位置: 首页 > web >正文

Java中使用Stream API优化for循环

业务逻辑:计算总额

原来使用for的逻辑代码

// 计算总额
double total = 0.0;
for (RkDetail rkDetail: rkDetailList) {if (rkDetail.getTotal() != null) {total += rkDetail.getTotal();}
}

使用Java 8 Stream API实现,使代码更简洁且易读 

// 计算总额
double total = rkDetailList.stream().filter(r -> r.getTotal() != null).mapToDouble(RkDetail::getTotal).sum();

让我们一步步拆解这段代码的含义,用生活中快递分拣的场景帮助你理解:

double total = rkDetailList.stream()      // 【开启传送带】.filter(r -> r.getTotal() != null)    // 【安检仪-过滤空包裹】.mapToDouble(RkDetail::getTotal)      // 【拆包取物】.sum();                               // 【自动累加】

1. 开启传送带 rkDetailList.stream()

想象你有一个装满快递包裹的货架(rkDetailList),现在要启动一条传送带处理这些包裹。
stream() 就像启动传送带,让包裹(列表中的每个 RkDetail 对象)依次进入处理流程。

📦📦📦📦 包裹们排着队进入传送带...


2. 安检仪过滤 filter(r -> r.getTotal() != null)

传送带上的第一个设备是安检仪,它会检查每个包裹:
r -> r.getTotal() != null 表示 "只允许装有金额的包裹通过"
(这里的 r 代表每个快递包裹,getTotal() 查看包裹内的金额单)

✅ 有金额单的包裹通过
❌ 空包裹(金额单为null)被丢弃

📦✅ -> 金额100元
📦❌ -> 金额单丢失
📦✅ -> 金额50元
📦✅ -> 金额200元


3. 拆包取物 mapToDouble(RkDetail::getTotal)

通过安检的包裹来到拆包工位,这里的工作人员会:
RkDetail::getTotal 表示 "拆开包裹,只取出里面的金额单"
mapToDouble 将金额单上的数字转换为计算机能直接计算的数值(double类型)

输入:📦✅ -> 输出:100.0
输入:📦✅ -> 输出:50.0
输入:📦✅ -> 输出:200.0


4. 自动累加 sum()

最后来到自动累加器,它会将所有金额单上的数值相加:
sum() 自动完成 100.0 + 50.0 + 200.0 = 350.0

💰 最终总额:350.0


完整流程示意图

原始包裹队列 → [传送带] → [安检过滤] → [拆包取数] → [自动求和](List)      (stream())   (filter)     (mapToDouble)   (sum)

重点记忆口诀

  1. 流式处理三步走:取流 → 过滤 → 转换

  2. 箭头符号看数据-> 左边是输入,右边是处理逻辑

  3. 双冒号是快捷方式类名::方法名 等价于 x -> x.方法名()

实际案例演示

假设原始数据:

RkDetail 包裹1 = new RkDetail(100.0);
RkDetail 包裹2 = new RkDetail(null);    // 空包裹
RkDetail 包裹3 = new RkDetail(50.0);
List<RkDetail> rkDetailList = Arrays.asList(包裹1, 包裹2, 包裹3);

代码执行过程:

  1. 包裹2 在 filter 阶段被过滤

  2. 包裹1 和 包裹3 的金额被提取

  3. 计算 100.0 + 50.0 = 150.0

最终 total 的值为 150.0

通过这种生活化的类比,是不是更容易理解Stream流的工作原理了呢?在实际开发中,这种处理方式比传统for循环更直观,尤其适合处理复杂的数据流水线操作。

 

优化点说明:

  1. Stream API 替代显式循环

    • 通过流式操作 stream() + filter() + mapToDouble() + sum() 链式调用,消除手动循环和中间变量,代码更简洁

    • 逻辑表达更声明式(描述做什么,而非如何做)

  2. 空值过滤更直观

    • filter(r -> r.getTotal() != null) 直接体现空值过滤逻辑,一目了然

  3. 避免中间状态变量

    • 原始代码需要维护 total 变量和循环体,流式操作直接通过无状态计算得到结果

扩展优化建议(视场景选用):

  1. 并行流加速

    java

    复制

    下载

    // 仅当列表极大且线程安全时使用
    double total = rkDetailList.parallelStream().filter(r -> r.getTotal() != null).mapToDouble(RkDetail::getTotal).sum();
  2. 空集合防御

    java

    复制

    下载

    // 如果 rkDetailList 可能为 null(根据业务场景决定是否添加)
    List<RkDetail> safeList = Optional.ofNullable(rkDetailList).orElse(Collections.emptyList());
    double total = safeList.stream()... // 后续操作同上
  3. 方法引用(若允许空值)

    java

    复制

    下载

    // 如果 RkDetail::getTotal 不可能返回 null(注意与当前场景冲突)
    double total = rkDetailList.stream().mapToDouble(RkDetail::getTotal).sum();

最终选择建议:
若运行环境是Java 8+且列表规模可控,推荐使用基础优化版本,兼顾简洁性与可维护性。

http://www.xdnf.cn/news/8726.html

相关文章:

  • [NOIP 2003 普及组] 麦森数 Java
  • AI要掌握的知识
  • Python_day35 模型可视化与推理
  • Java 内存模型(JMM)深度解析:理解多线程内存可见性问题
  • 网页 CSS美化2(详解)
  • Reason-ModernColBERT论文速览:内存受限设置下深度对比学习批量大小的扩展
  • IDA插件 MIPSROP的安装和使用方法
  • 电子人的分水岭-FPGA模电和数电
  • 大模型智能体入门扫盲——基于camel的概述
  • 嵌入式<style>设计模式
  • DeepSeek 赋能数字农业:从智慧种植到产业升级的全链条革新
  • 可编程运动控制器行业2025数据分析报告
  • CodeBuddy实现图片水印添加工具
  • Ntfs!ReadIndexBuffer函数分析之根目录读取索引缓冲区的一个例子
  • STM32 USART串口通信
  • Nginx-详解(二)
  • SOC-ESP32S3部分:11-任务创建
  • 事务处理与事务隔离
  • uni-app(5):Vue3语法基础上
  • Eigen 直线拟合/曲线拟合/圆拟合/椭圆拟合
  • Kotlin MultiPlatform 跨平台版本的记账 App
  • 39-居住证管理系统(小程序)
  • NRM:快速切换 npm 镜像源的管理工具指南
  • C/C++---隐式显式转换
  • World of Warcraft [CLASSIC] 80 Hunter [Grandel] VS Onyxia
  • 什么是深度学习中的层次分类问题?
  • C++静态成员变量
  • 使用 AWK 分析 CSV 文件中的数据模式
  • C++ --- string
  • 【MPC控制 - 从ACC到自动驾驶】车辆纵向动力学建模与离散化:MPC的“数字蓝图”