java stream的filter方法创建只含符合条件元素的新流,原始数据不变,惰性求值、不可变、支持链式调用;接收predicate判断元素,仅test返回true者进入后续流,需防null,多filter等价于and逻辑。

Java Stream 的 filter 方法不是“删掉不符合的元素”,而是构建一个**只包含符合条件元素的新流**——原始数据完全不变,整个过程是惰性求值、不可变、支持链式调用的。
filter 的核心逻辑:Predicate 判断 + 惰性执行
filter 接收一个 Predicate<t></t>(即返回 boolean 的函数),对每个元素调用其 test() 方法。只有返回 true 的元素才会出现在后续流中。注意:它不立即遍历,也不修改原集合,只是记录筛选规则;直到遇到终端操作(如 collect、forEach)时才真正执行。
- 写法必须返回
boolean,例如n -> n % 2 == 0✅,n -> System.out.println(n)❌ - 空值需主动防护,
filter(Objects::nonNull)可前置过滤 null - 多个
filter连用等价于“且”关系(AND),如先筛年龄 > 18,再筛城市为北京
常见过滤场景与写法示例
实际开发中,filter 最常用于业务属性判断和数据清洗:
- 字符串处理:去掉空串或空白串 ——
filter(s -> s != null && !s.trim().isEmpty()) - 数值范围:筛选价格在 [100, 500] 区间的产品 ——
filter(p -> p.getPrice() >= 100 && p.getPrice() - 对象属性匹配:查姓名以“A”开头且状态为激活的用户 ——
filter(u -> u.getName().startsWith("A") && u.isActive()) - 集合内判定:保留订单中至少含 3 个商品的订单 ——
filter(order -> order.getItems().size() >= 3)
容易踩的坑和注意事项
看似简单,但几个细节直接影响结果正确性和性能:
-
短路不适用:
filter不会提前终止,它必须检查每一个元素(不像anyMatch遇到第一个 true 就停) - 无状态要求:Predicate 必须是无状态的,不能依赖外部可变变量(如在 lambda 中修改某个计数器)
-
避免副作用:不要在
filter的 lambda 里做打印、写日志、修改对象等操作——这不是它的职责,且可能因惰性执行导致行为不可预期 -
性能提醒:对大数据量流,多个
filter链式调用比合并成一个条件(如用 &&)略低效,因为每个 filter 都要遍历一次;但可读性优先时,分拆更清晰
与其他中间操作的协作习惯
filter 往往不是单独使用的,它天然适合前置在 map、sorted、distinct 等操作之前,减少后续步骤的数据量:
- 先
filter再map:比如只转换有效订单的金额,避免对无效数据做无谓计算 - 先
filter再sorted:缩小排序范围,提升效率 - 配合
limit实现“找前 N 个满足条件的元素”:如filter(...).limit(5) - 与
peek搭配调试(仅限开发):filter(...).peek(System.out::println)查看哪些元素通过了筛选
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











