Java 8 Stream 流操作大全:从入门到实战全覆盖(附案例)
引言
Java 8 中的 Stream 是处理集合的终极利器,它提供了声明式、函数式的操作方式。本文将全面梳理 Stream 的核心操作及实际案例,适合所有 Java 开发者学习收藏!
🔍 一、什么是 Stream?
Stream 是 Java 8 引入的一个重要新特性,它不是数据结构,而是对集合(Collection)、数组等数据源进行链式、高效处理的一种方式。
特点:
- 声明式编程(更少的代码、更高的可读性)
- 支持并行(parallel)
- 不改变原数据源(函数式思想)
- 延迟执行(惰性求值)
🧱 二、Stream 的核心组成
类型 | 说明 |
---|---|
数据源 | 如 List、Set、数组、Map 的 entrySet 等 |
中间操作 | 多次链式调用,返回 Stream 自身 |
终结操作 | 最终计算结果,触发 Stream 执行链关闭 |
✨ 三、Stream 创建方式
✅ 从集合创建
List<String> list = Arrays.asList("a", "b", "c");
Stream<String> stream = list.stream();
✅ 从数组创建
String[] arr = {"a", "b", "c"};
Stream<String> stream = Arrays.stream(arr);
✅ 通过 Stream.of()
Stream<Integer> stream = Stream.of(1, 2, 3, 4);
✅ 无限流(函数式)
Stream<Integer> infinite = Stream.iterate(0, x -> x + 2).limit(5);
infinite.forEach(System.out::println); // 输出0 2 4 6 8
🧪 四、Stream 中间操作详解(中间操作不会立刻执行)
1️⃣ filter:过滤元素
List<String> list = Arrays.asList("apple", "banana", "cherry");
list.stream().filter(s -> s.startsWith("a")).forEach(System.out::println);
2️⃣ map:元素映射
List<String> upper = list.stream().map(String::toUpperCase).collect(Collectors.toList());
3️⃣ flatMap:扁平化嵌套结构
List<String> lines = Arrays.asList("a,b", "c,d", "e");
List<String> result = lines.stream().flatMap(s -> Arrays.stream(s.split(","))).collect(Collectors.toList());
4️⃣ distinct:去重
Stream.of(1, 2, 2, 3, 3).distinct().forEach(System.out::println);
5️⃣ sorted:排序
list.stream().sorted().forEach(System.out::println); // 默认自然排序
自定义排序:
list.stream().sorted((s1, s2) -> s2.length() - s1.length()).forEach(System.out::println);
6️⃣ limit / skip:限制/跳过元素
Stream.iterate(1, n -> n + 1).skip(3).limit(5).forEach(System.out::println); // 输出4,5,6,7,8
7️⃣ peek:调试用的中间操作
List<String> result = list.stream().peek(System.out::println).map(String::toUpperCase).collect(Collectors.toList());
🎯 五、Stream 终结操作详解(触发流执行)
1️⃣ forEach:遍历处理每个元素
list.stream().forEach(System.out::println);
2️⃣ collect:结果收集(常用于转为 List、Map)
List<String> upper = list.stream().map(String::toUpperCase).collect(Collectors.toList());
收集为 Map:
Map<String, Integer> map = list.stream().collect(Collectors.toMap(s -> s, String::length));
3️⃣ toSet / joining / groupingBy / partitioningBy
Set<String> set = list.stream().collect(Collectors.toSet());String joined = list.stream().collect(Collectors.joining(", "));Map<Integer, List<String>> grouped = list.stream().collect(Collectors.groupingBy(String::length));Map<Boolean, List<String>> partitioned = list.stream().collect(Collectors.partitioningBy(s -> s.contains("a")));
4️⃣ reduce:归约操作(聚合)
int sum = Stream.of(1, 2, 3, 4).reduce(0, Integer::sum);
5️⃣ count / min / max
long count = list.stream().count();Optional<String> max = list.stream().max(Comparator.comparing(String::length));
6️⃣ anyMatch / allMatch / noneMatch
boolean any = list.stream().anyMatch(s -> s.contains("a"));
boolean all = list.stream().allMatch(s -> s.length() > 2);
boolean none = list.stream().noneMatch(s -> s.startsWith("z"));
7️⃣ findFirst / findAny
Optional<String> first = list.stream().findFirst();
Optional<String> any = list.parallelStream().findAny();
🔄 六、实战案例综合
✅ 案例:按姓名分组统计员工人数
Map<String, Long> result = employees.stream().collect(Collectors.groupingBy(Employee::getName, Collectors.counting()));
✅ 案例:分区 -> 年龄是否大于 30
Map<Boolean, List<Employee>> partition = employees.stream().collect(Collectors.partitioningBy(e -> e.getAge() > 30));
✅ 案例:多条件排序(先按部门,再按年龄)
employees.stream().sorted(Comparator.comparing(Employee::getDepartment).thenComparing(Employee::getAge)).collect(Collectors.toList());
🚨 七、使用建议 & 注意事项
- Stream 是一次性操作,操作后不能再次使用
- 要避免流操作嵌套过深,影响可读性
- 注意延迟执行行为,中间操作不触发执行
- 尽量避免使用
collect().get()
导致空指针异常
📚 八、总结:流操作速查表
操作类型 | 方法 | 说明 |
---|---|---|
创建 | stream() , of() , iterate() | 创建流 |
中间操作 | filter , map , flatMap , distinct , sorted , limit , skip , peek | 构建处理链 |
终结操作 | forEach , collect , reduce , count , anyMatch , findFirst , toMap 等 | 执行处理,返回结果 |
🔚 九、推荐扩展阅读
- 《Java 8 实战》
- Oracle 官方文档:https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html
📌 点赞 + 收藏 + 关注,每天带你掌握底层原理,写出更强健的 Java 代码!