拒绝写臃肿的 for 循环!Java 8 Stream 流从入门到实战
·
一、 什么是 Stream 流?
简单来说,Stream(流)就是Java 8 提供的一套处理集合(List, Set, Map)的工具 API。
不要把它和 IO 流(FileInputStream)混淆。IO 流是处理“文件传输”的,而 Stream 流是处理“内存数据计算”的。
它的核心思想是: 把集合看作一条流水线,元素在上面流动,我们可以经过一系列的工序(过滤、去重、映射、排序),最后包装成我们需要的结果。
为什么要用它?
- 代码简洁:告别层层嵌套的
if-else和for循环。 - 逻辑清晰:一看代码就知道在做什么(声明式编程)。
- 功能强大:一行代码搞定过滤、排序、分组、转换。
二、 Stream 流的“三板斧”
使用 Stream 流,永远只有三个步骤:
数据源 -> 中间操作 -> 终结操作
- 开启流 (Source):把集合变成流(如
list.stream())。 - 中间操作 (Intermediate):对流里的数据进行处理(过滤、转换、排序等)。注意:中间操作是“懒”的,不碰到终结操作绝不干活。
- 终结操作 (Terminal):把流里的数据收集起来,变成 List、Map 或者直接打印。
三、 实战:最常用的 4 个场景
场景 1:类型转换 / 对象映射 (Map) 最常用
需求:从数据库查出了一堆 User 实体对象,包含了密码等敏感信息。现在需要把它们转换成 UserDTO 传给前端。
以前的写法 (for 循环):
Java
List<UserDTO> dtoList = new ArrayList<>();
for (User user : userList) {
UserDTO dto = new UserDTO();
// 假设用了 Hutool
BeanUtil.copyProperties(user, dto);
dtoList.add(dto);
}
Stream 写法:
Java
List<UserDTO> dtoList = userList.stream() // 1. 开流
.map(user -> BeanUtil.copyProperties(user, UserDTO.class)) // 2. 映射:把 User 变成 UserDTO
.collect(Collectors.toList()); // 3. 收集
解析:
.map()是最核心的方法,它的意思是“把流里的每一个元素,变成另一个东西”。
场景 2:数据过滤 (Filter)
需求:找出一堆博客中,点赞数大于 100 的那些博客。
Stream 写法:
Java
List<Blog> hotBlogs = records.stream()
.filter(blog -> blog.getLiked() > 100) // 2. 过滤:返回 true 的留下,false 的扔掉
.collect(Collectors.toList());
场景 3:类型强转与处理 (map + 方法引用)
需求:Redis 里取出的 ID 是 String 类型的(如 "101", "102"),需要转成 Long 类型去查数据库。
Stream 写法:
Java
List<String> idStrs = Arrays.asList("101", "102", "103");
List<Long> ids = idStrs.stream()
.map(Long::valueOf) // 等同于 .map(s -> Long.valueOf(s))
.collect(Collectors.toList());
场景 4:去重与排序 (Distinct & Sorted)
需求:有一堆无序且重复的数字,想给它们排序并去重。
Stream 写法:
Java
List<Integer> numbers = Arrays.asList(3, 1, 4, 1, 5, 9, 2, 6);
List<Integer> result = numbers.stream()
.distinct() // 去重
.sorted() // 排序 (默认从小到大)
.collect(Collectors.toList());
// 结果:[1, 2, 3, 4, 5, 6, 9]
四、 进阶:List 转 Map
这是开发中非常高频的场景。 需求:有一个 User 列表,我想变成一个 Map<Long, User>,key 是 userId,value 是 User 对象本身,方便后续通过 ID 快速查找。
Stream 写法:
Java
Map<Long, User> userMap = userList.stream()
.collect(Collectors.toMap(User::getId, user -> user));
解析:
Collectors.toMap接收两个参数,第一个指定谁做 Key,第二个指定谁做 Value。
更多推荐


所有评论(0)