文章的整体框架由ChatGPT5进行生成,作者根据框架进行内容编写。
前言
入职一个多月以来,在日常开发中我发现一个使用到的非常高频的工具或者说API吧,那就是:Java Stream 流
不论是处理集合数据、过滤业务对象、还是对查询结果进行统计汇总,Stream 几乎无处不在。
如果说 List 是数据的容器,那么 Stream 就是让数据“动”起来的流水线。
这篇文章将结合我这段时间的项目体会,从概念、常用操作、实战案例三个方面,带大家深入理解 Stream 流。
一、Stream 是什么?
Stream 是 Java 8 引入的新特性,用于对集合(如 List、Set、Map)进行函数式操作。
它的核心思想是:
用声明式的方式对数据进行处理,而不是写 for 循环。
传统写法:
List<String> names = new ArrayList<>();
for (User user : userList) {
if (user.getAge() > 18) {
names.add(user.getName());
}
}Stream 写法:
List<String> names = userList.stream()
.filter(user -> user.getAge() > 18)
.map(User::getName)
.collect(Collectors.toList());通过对比是不是一眼清爽多了?代码更加的简洁、更容易读懂,也更容易维护。
二、Stream 的常见操作
Stream 的操作主要分为三类:
| 类型 | 方法 | 说明 |
|---|---|---|
| 创建流 | stream()、of() |
从集合或数组创建流 |
| 中间操作 | filter()、map()、sorted()、distinct()、limit()、skip()、flatMap() |
用于数据处理和转换 |
| 终止操作 | collect()、forEach()、count()、findFirst()、allMatch()、anyMatch()、noneMatch() |
产生结果或副作用 |
1. 创建流
List<String> list = Arrays.asList(\"Java\", \"Python\", \"C++\");
Stream<String> stream = list.stream(); // 从集合创建流
Stream<Integer> intStream = Stream.of(1, 2, 3, 4, 5); // 从数组创建流
2. 中间操作(返回新的 Stream)
list.stream()
.filter(s -> s.length() > 3)3. 终止操作(生成结果)
List<String> result = list.stream()
.filter(s -> s.contains(\"a\"))
.collect(Collectors.toList());三、实战:在实际开发业务中使用 Stream
举个我在工作中遇到的例子:
需求:从数据库查出的设备列表中,筛选出租赁中(status = "using")的设备,按部门分组并统计数量。
假设我们有一个实体类:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Device {
private String id;
private String name;
private String department;
private String status;
}List<Device> devices = Arrays.asList(
new Device(\"1\", \"挖掘机A\", \"土建部\", \"using\"),
new Device(\"2\", \"吊车B\", \"机电部\", \"idle\"),
new Device(\"3\", \"挖掘机C\", \"土建部\", \"using\"),
new Device(\"4\", \"泵车D\", \"机电部\", \"using\")
);
需求 1:筛选出“使用中”的设备
List<Device> usingDevices = devices.stream()
.filter(d -> \"using\".equals(d.getStatus()))
.collect(Collectors.toList());
需求 2:统计每个部门的设备数量
Map<String, Long> countByDept = devices.stream()
.collect(Collectors.groupingBy(Device::getDepartment, Collectors.counting()));输出结果:
{机电部=2, 土建部=2}需求 3:获取设备名称列表并拼接成字符串
String names = devices.stream()
.map(Device::getName)
.collect(Collectors.joining(\", \"));
System.out.println(names);
// 输出:挖掘机A, 吊车B, 挖掘机C, 泵车D
四、Stream 的一些高级用法
分组 + 过滤 + 映射 组合操作
Map<String, List<String>> deptDeviceNames = devices.stream()
.filter(d -> \"using\".equals(d.getStatus()))
.collect(Collectors.groupingBy(
Device::getDepartment,
Collectors.mapping(Device::getName, Collectors.toList())
));
结果:
{机电部=[泵车D], 土建部=[挖掘机A, 挖掘机C]}求和与平均值
List<Integer> nums = Arrays.asList(10, 20, 30, 40);
int sum = nums.stream().mapToInt(Integer::intValue).sum();
double avg = nums.stream().mapToInt(Integer::intValue).average().orElse(0);五、总结
Stream 并不是为了“耍酷”,"看起来高级",而是让我们:
- 更 高效 地操作集合数据
- 更 优雅 地表达业务逻辑
- 更 专注 于 “做什么”,而不是 “怎么做”
入职这段时间,我深刻体会到stream流的熟练使用会使开发效率大大提高。如果你还没在项目中使用过 Stream,建议从小模块开始尝试,相信你很快就会离不开它。
后记
后续我会继续补充一些关于stream流的高级用法,如:
Collectors高级用法(分区、嵌套分组)ParallelStream并行流的性能与坑- 以及在 Spring Cloud项目中实际使用 Stream 的最佳实践
非常感谢你能读到这里,欢迎关注、收藏,一起进步!
评论