一、Stream 的整体结构
一条 Stream 永远是三段式:
list.stream() // 数据源
.filter(...) // 中间
.map(...) // 中间
.forEach(...); // 终止
没有终止操作,Stream 不会执行
二、最常用的中间操作
1、filter —— 过滤(if)
.filter(x -> x > 10)
等价 for 循环:
if (x > 10) {
...
}
工程用途:
- 按状态筛选
- 过滤空值
- 条件查询结果集
2、map —— 转换(改对象 / 改字段)
.map(User::getName)
.map(u -> {
u.setAge(18);
return u;
})
等价于
String name = user.getName();
map 不一定返回新对象,也可以改原对象(虽然不推荐)
3、flatMap —— 拍平(非常重要)
List<List> list;
list.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
List<List<T>> → List<T>
4、distinct —— 去重
依赖 equals + hashCode去重,对象需要实现hashcode()和equals()方法。
5、sorted —— 排序
.sorted() // 自然顺序
.sorted(Comparator.comparing(User::getAge))
.sorted((a, b) -> b.getAge() - a.getAge())
6、limit / skip —— 分页 / 截断
.skip(10)
.limit(10)
三、终止操作(必须)
1、forEach —— 遍历
.forEach(System.out::println);
2、collect —— 收集成集合(最重要)
.collect(Collectors.toList())
.collect(Collectors.toSet())
.collect(Collectors.toMap(
User::getId,
User::getName
))
toMap 超级常见坑
.collect(Collectors.toMap(
User::getId,
User::getName,
(a, b) -> a // key 冲突时取哪个
))
3、reduce —— 归并(求和 / 拼接)
int sum = list.stream()
.reduce(0, Integer::sum);
4、count / max / min / anyMatch(实用)
long count = list.stream().count();
Optional max =
list.stream().max(Comparator.comparing(User::getAge));
boolean exists =
list.stream().anyMatch(u -> u.getAge() > 18);
四、最常见的组合套路
1、过滤 + 转换 + 收集(最常见)
List names =
users.stream()
.filter(u -> u.getAge() > 18)
.map(User::getName)
.collect(Collectors.toList());
2、判空 + 安全处理(避免 NPE)
List safe =
Optional.ofNullable(users)
.orElse(Collections.emptyList())
.stream()
.collect(Collectors.toList());
3、分组(代替 for + Map)
Map<String, List> map =
users.stream()
.collect(Collectors.groupingBy(User::getDept));
4、转 Map(后端非常多)
Map<Long, User> userMap =
users.stream()
.collect(Collectors.toMap(
User::getId,
u -> u
));
8 个核心方法
| 分类 | 方法 |
|---|---|
| 中间 | filter |
| 中间 | map |
| 中间 | flatMap |
| 中间 | sorted |
| 中间 | distinct |
| 终止 | forEach |
| 终止 | collect |
| 终止 | anyMatch |
文章评论