news 2026/9/21 6:11:35

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/22 1:17:17

基于微信小程序的动漫社区交流小程序的设计与实现(源码+lw+部署文档+讲解等)

课题介绍本课题聚焦动漫爱好者交流渠道分散、优质内容聚合不足的痛点&#xff0c;设计实现基于微信小程序的动漫社区交流小程序。依托微信小程序轻量化、易传播的特性&#xff0c;为动漫爱好者搭建便捷的线上交流平台。系统后端搭建稳定的数据管理架构&#xff0c;支撑用户信息…

作者头像 李华
网站建设 2026/9/21 7:36:09

响应格式化踩坑实录:Symfony 8开发者必须避开的5个陷阱

第一章&#xff1a;响应格式化踩坑实录&#xff1a;Symfony 8开发者必须避开的5个陷阱 在 Symfony 8 的开发过程中&#xff0c;响应格式化是构建 RESTful API 的核心环节。然而&#xff0c;许多开发者因忽略细节而陷入常见陷阱&#xff0c;导致性能下降或接口行为异常。 忽视 …

作者头像 李华
网站建设 2026/9/22 2:05:57

PHP 8.6性能监控面板实战(专家级配置全公开)

第一章&#xff1a;PHP 8.6性能监控的核心价值与架构演进 随着现代Web应用对响应速度和系统稳定性的要求不断提升&#xff0c;PHP 8.6在性能优化方面引入了多项底层改进&#xff0c;使得运行时效率显著提升。然而&#xff0c;性能的可观测性依赖于完善的监控体系&#xff0c;因…

作者头像 李华
网站建设 2026/9/22 1:17:38

性能监控在DevOps中的角色

在敏捷开发与持续交付成为主流的今天&#xff0c;DevOps理念已深度重塑软件工程实践。作为质量保障的关键环节&#xff0c;软件测试正从传统的阶段性验证向全流程质量守护演进。性能监控作为贯穿DevOps流水线的"神经系统"&#xff0c;正为测试从业者提供前所未有的洞…

作者头像 李华
网站建设 2026/9/19 0:07:14

RN Hooks 设计规范与反模式清单

[toc] 如果你写 RN 写到后面&#xff0c;开始出现下面这些情况&#xff1a; 一个页面引用 5&#xff5e;8 个自定义 Hook一个 Hook 内部 300 行&#xff0c;还不敢拆useEffect 嵌套 useEffect&#xff0c;依赖数组随缘写改一个状态&#xff0c;引发一连串莫名其妙的更新 那问题…

作者头像 李华