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

Java 8 Stream API 入门到实践详解

一、告别 for 循环!

传统痛点
Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数:

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> evens = new ArrayList<>();
for (Integer num : list) {if (num % 2 == 0) evens.add(num);
}

Stream 救场
一行代码搞定:

List<Integer> evens = list.stream().filter(x -> x % 2 == 0).collect(Collectors.toList());

核心优势

  • 简洁:链式调用替代复杂循环。
  • 高效:惰性计算(Lazy Evaluation),按需执行。
  • 并行:一键切换并行处理,提升性能。

二、Stream 三大核心操作:过滤、映射、归约
1. 过滤(filter):筛出想要的元素

作用:只保留符合条件的元素。
语法filter(Predicate<T> predicate)
示例:筛选长度超过3的字符串

List<String> languages = Arrays.asList("Java", "Python", "C++", "Go");
List<String> filtered = languages.stream().filter(s -> s.length() > 3).collect(Collectors.toList());
// 结果: ["Java", "Python"]

底层逻辑:遍历流中每个元素,保留 predicate.test(element)true 的元素。
注意filter中间操作,返回新流,需配合终端操作(如 collect)才能执行。


2. 映射(map):元素转换

作用:将元素转换为另一种形式。
语法map(Function<? super T, ? extends R> mapper)
示例:将字符串转为大写

List<String> upperCase = languages.stream().map(String::toUpperCase).collect(Collectors.toList());
// 结果: ["JAVA", "PYTHON", "C++", "GO"]

进阶玩法

  • 扁平化嵌套集合:用 flatMap 展开多层结构
     
    List<List<String>> nested = Arrays.asList(Arrays.asList("a", "b"),Arrays.asList("c", "d"));
    List<String> flat = nested.stream().flatMap(Collection::stream).collect(Collectors.toList());
    // 结果: ["a", "b", "c", "d"]
    


3. 归约(reduce):聚合数值,合二为一

作用:将元素合并为一个值(如求和、拼接字符串)。
语法reduce(T identity, BinaryOperator<T> accumulator)
示例:计算整数列表的总和

List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
int sum = numbers.stream().reduce(0, Integer::sum);
// 结果: 10

魔法细节

  • identity 是初始值(如求和时设为 0)。
  • accumulator 定义如何合并元素(如 a + b)。

三、实战:从新手到封神的 3 个场景
场景1:统计文本中单词频率
String text = "java stream api is powerful and easy to use";
Map<String, Long> wordCount = Arrays.stream(text.split(" ")).collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
// 结果: {java=1, stream=1, api=1, ...}

关键点

  • split(" ") 分割字符串为流。
  • groupingBy 按单词分组,counting 统计次数。

场景2:并行处理大数据(真香警告)
List<Integer> largeList = IntStream.range(0, 1000000).parallel() // 切换并行流.filter(x -> x % 2 == 0).boxed().collect(Collectors.toList());
System.out.println(largeList );

效率对比

  • 串行流处理100万数据:约500ms。
  • 并行流处理:约100ms(8核CPU)。

场景3:多级排序(薪资+年龄)
class Employee {String name;int salary;int age;// constructor & getters
}List<Employee> sorted = employees.stream().sorted(Comparator.comparing(Employee::getSalary).thenComparing(Employee::getAge)).collect(Collectors.toList());
System.out.println(sorted);

技巧:链式 Comparator 实现多条件排序。


四、避坑指南:新手常踩的雷区
  1. 流只能使用一次

    Stream<Integer> stream = numbers.stream();
    stream.forEach(System.out::println); // 正常
    stream.forEach(System.out::println); // 报错!流已关闭
    
  2. 避免修改外部变量
    
    int count = 0;
    numbers.stream().forEach(n -> count++); // 错误!并行流下可能出错
    
  3. 并行流未必更快

    • 小数据量:串行更优(省去线程切换开销)。
    • 大数据量+复杂操作:并行提速显著。

五、总结:Stream API 的江湖地位
操作传统方式Stream 写法爽点
过滤偶数for + iffilter(x -> x%2==0)代码量减半
字符串转大写循环+toUpperCasemap(String::toUpperCase)一行搞定
统计总数for 累加reduce(0, Integer::sum)函数式编程优雅度拉满
http://www.lqws.cn/news/201295.html

相关文章:

  • 【高效开发工具系列】Blackmagic Disk Speed Test for Mac:专业硬盘测速工具
  • CMS、G1、ZGC、Shenandoah 的全面对比
  • 前端模块化
  • Node.js: express 使用 Open SSL
  • 十、【ESP32开发全栈指南: TCP客户端】
  • TDengine 支持的平台汇总
  • 微软PowerBI考试 PL300-使用适用于 Power BI 的 Copilot 创建交互式报表
  • 1.5 Node.js 的 HTTP
  • PDF图片和表格等信息提取开源项目
  • 使用 Laravel 中的自定义存根简化工作
  • 计算机组成与体系结构:补码数制二(Complementary Number Systems)
  • 数据表自增主键命名规范
  • STM32学习之I2C(理论篇)
  • 【C++字符串基础解析1】
  • 网络原理5 - TCP4
  • C# 中替换多层级数据的 Id 和 ParentId,保持主从或父子关系不变
  • MySQL中的内置函数
  • 统一点云数据格式:高效转换与属性保留
  • 自适应长度惩罚强化学习的高效推理
  • Conda环境备份教程
  • Spring事务和事务传播机制
  • 隐私计算时代B端页面安全设计:数据脱敏与权限体系升级路径
  • 力扣面试150题--除法求值
  • 【力扣】2434.使用机器人打印字典序最小的字符串
  • 实战二:开发网页端界面完成黑白视频转为彩色视频
  • 腾讯开源视频生成工具 HunyuanVideo-Avatar,上传一张图+一段音频,就能让图中的人物、动物甚至虚拟角色“活”过来,开口说话、唱歌、演相声!
  • 微前端 - Native Federation使用完整示例
  • 计算机是如何⼯作的
  • 【Linux shell】shell中的变量——构建脚本逻辑的基石
  • qt使用笔记二:main.cpp详解