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

270. Java Stream API - 从“怎么做”转向“要什么结果”:声明式编程的优势

文章目录

    • 270. Java Stream API - 从“怎么做”转向“要什么结果”:声明式编程的优势
      • 🎯 目标任务
      • 🧱 传统命令式写法(Java 代码)
      • 💡 思维实验:如果 Collection 有 map 和 filter 会怎样?
      • ❌ 性能陷阱:中间集合的隐性开销
    • ✅ 为什么是 Stream,而不是 Collection?
      • 🌊 Stream 的关键特性:**不存储数据,只描述处理过程**
      • 🧠 懒加载(Lazy Evaluation):终端操作才“开水龙头”
      • ⚙️ 示例:短路操作节省时间
    • 📊 总结:为什么 map/filter 不属于 Collection 接口?
    • 🧵 Stream API 的流水线模型:终端操作才“触发机器运转”
    • 📘 实操建议(练习题):

270. Java Stream API - 从“怎么做”转向“要什么结果”:声明式编程的优势

🎯 目标任务

我们要计算一个城市列表中,人口超过 10 万的城市总人口数


🧱 传统命令式写法(Java 代码)

recordCity(intpopulation){}List<City>cities=List.of(newCity(100_000),newCity(200_000),newCity(500_000));intsum=0;for(Citycity:cities){intpopulation=city.population();if(population>100_000){sum+=population;}}System.out.println("Sum = "+sum);// 输出:700000

这段代码很好地完成了目标,但是命令式的——一步一步告诉程序要做什么。


💡 思维实验:如果 Collection 有 map 和 filter 会怎样?

假设我们扩展Collection接口,给它添加map()filter()方法,并且它们返回的是Collection

Collection<Integer>populations=cities.map(city->city.population());Collection<Integer>filteredPopulations=populations.filter(p->p>100_000);intsum=filteredPopulations.sum();

看起来很“链式”,很优雅,但有一个严重问题每一步都要创建中间集合!


❌ 性能陷阱:中间集合的隐性开销

  • map()会遍历所有城市,并创建一个新的集合保存每个城市的人口数。
  • filter()会再遍历这个人口集合,选出符合条件的。
  • sum()会再遍历过滤结果做加总。

👉 如果处理上百万城市对象,那么这会造成大量内存分配和垃圾回收压力

而传统的for循环是一边遍历、一边判断、一边累加的,没有任何中间结构的创建


✅ 为什么是 Stream,而不是 Collection?

🌊 Stream 的关键特性:不存储数据,只描述处理过程

intsum=cities.stream().mapToInt(City::getPopulation)// 先映射成人口数.filter(p->p>100_000)// 筛选出人口超 10 万的.sum();// 聚合求和(终端操作)

在这段代码中:

  • 没有中间集合产生;
  • .mapToInt().filter()都是中间操作,只是“排管道”;
  • .sum()终端操作,才真正触发数据流动和计算。

🧠 懒加载(Lazy Evaluation):终端操作才“开水龙头”

  • Stream就像“工厂流水线”,每个操作(map/filter)都是一个加工环节;
  • 只有当你调用.sum().collect()等终端操作时,才真的开始处理每个数据;
  • 每个数据只“走一次管道”:

💡 不是“先映射完所有人口” ➝ “再筛选” ➝ “再加总”,
而是:每个城市 ➝ 映射 ➝ 判断是否保留 ➝ 累加(即一条龙服务🚀)。


⚙️ 示例:短路操作节省时间

需求:判断是否存在人口超过 100_000 的城市

传统 Collection 风格必须遍历:

booleanexists=cities.map(City::population).filter(p->p>100_000).anyMatch(p->true);// 已经浪费了两步处理

而用 Stream 可以做到只看第一个符合条件的城市

booleanexists=cities.stream().anyMatch(c->c.getPopulation()>100_000);

💥 一旦遇到满足条件的城市,就立即返回true,后续不再处理!


📊 总结:为什么 map/filter 不属于 Collection 接口?

方式map/filter 返回类型是否创建中间集合是否惰性求值是否支持短路
Collection.map()Collection✅ 会创建❌ 否❌ 否
Stream.map()Stream❌ 不创建✅ 是✅ 是(如 anyMatch)

👉 正因为Collection 是数据容器,而Stream 是操作流水线,所以map()filter()被设计在Stream而非Collection


🧵 Stream API 的流水线模型:终端操作才“触发机器运转”

操作类型举例描述
中间操作map(),filter(),sorted()返回 Stream,不触发计算
终端操作sum(),collect(),forEach()返回非 Stream,触发计算

📘 实操建议(练习题):

  1. 使用stream()实现:计算人口超过 200_000 城市的平均人口;
  2. 统计有多少个城市符合人口 > 100_000;
  3. 判断是否所有城市人口都 > 50_000。
http://www.cnnetsun.cn/news/68965.html

相关文章:

  • 基于微信小程序的动漫社区交流小程序的设计与实现(源码+lw+部署文档+讲解等)
  • 响应格式化踩坑实录:Symfony 8开发者必须避开的5个陷阱
  • PHP 8.6性能监控面板实战(专家级配置全公开)
  • 性能监控在DevOps中的角色
  • RN Hooks 设计规范与反模式清单
  • 《Advanced Science》最新研究:多自由度折纸模块构建可编程机械超材料网络
  • 用梯形图+SCL玩转FactoryIO码垛控制
  • 7、Nagios 安装与功能拓展全解析
  • 读懂 NVIDIA Jetson OP-TEE 官方源码:从目录结构到 JetPack / Yocto 构建与运行的完整指南
  • LobeChat能否实现邀请码注册机制?控制用户增长节奏
  • Angular AOT编译失败?这份官方文档解读帮你10分钟定位问题
  • PHP环境下医疗数据备份怎么做?5种高可用方案对比分析
  • 【Python库选型避坑手册】:5年踩坑经验总结出的7条黄金法则
  • PHP 8.6 JIT编译器重大升级(指令优化黑科技曝光)
  • Keil串口通信全教程:UART初始化、数据收发(中断/查询模式)+串口调试助手验证
  • 揭秘WebSocket频繁断线之谜:3种常见错误码分析与修复方案
  • LPDDR6 JEDEC 原文解读学习—2.4 Data Packet Format(3)(~持续更新)
  • 【PHP性能优化关键一步】:深入PHP 8.6内存泄漏监控与自动预警方案
  • PHP 8.6兼容性测试实战(资深架构师亲授迁移经验)
  • 从入门到精通:用R Shiny打造可交互的多维度数据仪表盘
  • 光伏阵列遇到局部阴影就像吃火锅被隔壁桌抢肉——憋屈得很。今天咱们用Python整活,搞个3×3电池板的阴影仿真模型,重点观察串联结构在阴影下的输出曲线怎么抽风
  • 你还不知道HTTP/3的这5个性能秘密?:资深架构师20年经验倾囊相授
  • 如何将EF Core响应时间降低80%?一线大厂都在用的4种策略
  • BGP综合实验
  • 大数据采集与处理技术实训室
  • 基于MATLAB 火灾检测系统,可以实现图片的火苗检测。 推荐matlab2019A及以后。
  • Harmony学习之本地数据存储
  • 【PHP扩展性能优化秘籍】:基于Rust的函数调试与内存泄漏排查指南
  • Flutter 状态管理终极指南(一):从 setState 到 Riverpod 2.0
  • Symfony 8路由缓存机制揭秘:如何让应用加载快如闪电