Java Stream API 的 filter() 配合 Predicate 是实现复杂条件过滤最自然、最可读的方式,关键在于拆分清晰、组合精准、边界可控,支持 and/or/negate 逻辑组合、动态条件拼装、嵌套与集合深度判断及 null 安全预处理。

Java Stream API 的 filter() 方法配合 Predicate,是实现复杂条件过滤最自然、最可读的方式。关键不在于写得“多”,而在于拆得清、组合得准、边界控得住。
用 and/or/negate 组合多个独立条件
把每个业务含义明确的判断抽成单独的 Predicate,再用逻辑方法拼接,比堆在一个 Lambda 里更易理解、复用和测试。
-
adult.and(active):必须同时满足(“且”) -
admin.or(moderator):满足其一即可(“或”) -
notDeleted.negate():取反(“非”),等价于s -> !s.isDeleted()
示例:
Predicate<User> adult = u -> u.getAge() >= 18;
Predicate<User> active = u -> "ACTIVE".equals(u.getStatus());
Predicate<User> admin = u -> "ADMIN".equals(u.getRole());
List<User> result = users.stream()
.filter(adult.and(active).or(admin))
.collect(Collectors.toList());
动态条件拼装:按需叠加有效规则
前端传参或配置驱动的筛选场景中,不能硬编码所有组合。推荐以 Predicate.alwaysTrue() 为起点,只对非空/有效参数追加条件。
立即学习“Java免费学习笔记(深入)”;
- 年龄下限不为空 → 追加
age >= minAge - 状态值存在 → 追加
status.equals(inputStatus) - 角色列表非空 → 追加
roles.contains(role)
代码片段:
Predicate<User> filter = Predicate.alwaysTrue();
if (minAge != null) {
filter = filter.and(u -> u.getAge() >= minAge);
}
if (StringUtils.isNotBlank(status)) {
filter = filter.and(u -> status.equals(u.getStatus()));
}
if (CollectionUtils.isNotEmpty(roles)) {
filter = filter.and(u -> roles.contains(u.getRole()));
}
return users.stream().filter(filter).collect(Collectors.toList());
嵌套对象与集合字段的深度判断
Stream 过滤支持任意层级访问,但要注意空指针风险。对嵌套属性,优先用 Objects.nonNull() 或 Optional 防御;对集合字段,常用 anyMatch() / allMatch() / noneMatch() 判断内部元素。
order.getAddress() != null && "Beijing".equals(order.getAddress().getCity())order.getItems().stream().anyMatch(item -> item.getPrice() > 100)- 合并写法:
filter(o -> Objects.nonNull(o.getAddress()) && "Beijing".equals(o.getAddress().getCity()) && o.getItems().stream().anyMatch(...))
预处理 null 和脏数据是安全底线
真实数据常含 null、空字符串、空白字符串。应在 filter 链最前统一清理,避免后续调用抛出 NullPointerException。
- 字符串:先
s != null && !s.trim().isEmpty() - 对象引用:用
Objects::nonNull或显式判空 - 数值字段:注意包装类可能为
null,建议用Objects.nonNull(u.getAge()) && u.getAge() > 18
示例:
List<String> data = Arrays.asList("Java", null, " ", "Python", "");
List<String> clean = data.stream()
.filter(Objects::nonNull)
.filter(s -> !s.trim().isEmpty())
.collect(Collectors.toList()); // [Java, Python]


















