本文目录导读:

- 基础案例:筛选年龄大于18的用户
- 多条件筛选:名字以A开头 且 年龄大于18
- 排除/取反:筛选未成年(年龄 < 18)
- 去重后筛选:结合
distinct() - 复杂对象属性筛选
- ⚠️ 几个容易被忽略的细节(面试常问)
Java Stream 的 filter() 方法是用来筛选数据最核心的工具,它接收一个 Predicate(断言函数,即返回 boolean 的 Lambda 表达式),保留满足条件的元素。
下面为你提供 5 个从简单到复杂的实战案例,覆盖最常见的筛选场景。
基础案例:筛选年龄大于18的用户
场景:从一个用户列表中找出成年人。
import java.util.List;
import java.util.stream.Collectors;
public class StreamFilterExample {
public static void main(String[] args) {
// 准备数据
List<User> users = List.of(
new User("Alice", 25),
new User("Bob", 17),
new User("Charlie", 19),
new User("David", 16)
);
// 筛选年龄 >= 18 的用户
List<User> adults = users.stream()
.filter(user -> user.getAge() >= 18) // 关键:条件表达式
.collect(Collectors.toList());
System.out.println(adults);
// 输出:[User(name=Alice, age=25), User(name=Charlie, age=19)]
}
}
// 辅助类
class User {
private String name;
private int age;
// 构造方法、getter、toString 略(需要自己补全)
public User(String name, int age) {
this.name = name;
this.age = age;
}
public int getAge() { return age; }
public String getName() { return name; }
@Override
public String toString() {
return "User(name=" + name + ", age=" + age + ")";
}
}
关键点:
filter()内部是 Lambda:user -> user.getAge() >= 18。- 返回
true的保留,false的丢弃。
多条件筛选:名字以A开头 且 年龄大于18
场景:筛选名字以 "A" 开头且成年的人。
List<User> result = users.stream()
.filter(user -> user.getName().startsWith("A") && user.getAge() >= 18)
.collect(Collectors.toList());
// 结果:[User(name=Alice, age=25)]
也可以分步写(更清晰):
Predicate<User> nameStartsWithA = user -> user.getName().startsWith("A");
Predicate<User> ageAdult = user -> user.getAge() >= 18;
List<User> result = users.stream()
.filter(nameStartsWithA.and(ageAdult)) // 使用 Predicate 的 and()
.collect(Collectors.toList());
排除/取反:筛选未成年(年龄 < 18)
场景:找出年龄小于 18 的用户。
直接写条件
List<User> minors = users.stream()
.filter(user -> user.getAge() < 18)
.collect(Collectors.toList());
// 结果:[User(name=Bob, age=17), User(name=David, age=16)]
使用 Predicate.negate()(取反)
Predicate<User> isAdult = user -> user.getAge() >= 18;
List<User> minors = users.stream()
.filter(isAdult.negate()) // 取反,相当于 !isAdult
.collect(Collectors.toList());
去重后筛选:结合 distinct()
场景:有一个包含重复元素的列表,筛选出偶数并去重。
List<Integer> numbers = List.of(1, 2, 2, 3, 4, 4, 5, 6);
List<Integer> evenDistinct = numbers.stream()
.filter(n -> n % 2 == 0) // 筛选偶数
.distinct() // 去重
.collect(Collectors.toList());
System.out.println(evenDistinct); // 输出:[2, 4, 6]
复杂对象属性筛选
场景:有一个订单列表 Order,每个订单包含 amount(金额)和 status(状态)。
需求:找出状态为 “PAID” 且金额大于 100 的订单。
List<Order> orders = List.of(
new Order("001", 150.0, "PAID"),
new Order("002", 50.0, "PAID"),
new Order("003", 200.0, "UNPAID")
);
List<Order> paidHighValue = orders.stream()
.filter(order -> "PAID".equals(order.getStatus()) && order.getAmount() > 100)
.collect(Collectors.toList());
System.out.println(paidHighValue);
// 输出:[Order(id=001, amount=150.0, status=PAID)]
⚠️ 几个容易被忽略的细节(面试常问)
-
filter()不会修改原数据users.stream().filter(u -> u.getAge() > 18).collect(...); // users 列表本身不变,这是函数式编程的特点(无副作用)
-
顺序问题:
filter()放在前面可以减少后续操作的数据量,提升性能。// 推荐:先过滤,再 map list.stream() .filter(...) // 先减少数据 .map(...) // 再处理少量数据 -
空指针风险:
User::getName可能为null,直接调用startsWith()会报NullPointerException。// 安全写法 .filter(user -> user.getName() != null && user.getName().startsWith("A")) // 或者使用 Objects::nonNull .filter(user -> Objects.nonNull(user.getName()) && user.getName().startsWith("A"))
| 场景 | 写法 |
|---|---|
| 单条件 | filter(x -> x > 5) |
| 多条件 AND | filter(x -> x > 5 && x < 10) |
| 多条件 OR | filter(x -> x > 5 \|\| x < 0) |
| 取反 | filter(Predicate.not(x -> x > 5)) 或 filter(x -> !(x > 5)) |
| 配合 distinct | filter(...).distinct() |
| 配合 limit | filter(...).limit(5) (只要前5个满足条件的) |
如果你有具体的业务场景(比如筛选日期范围、模糊匹配字符串等),可以告诉我,我可以帮你写出对应的案例。
版权声明:足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播