Java Stream API过滤集合分三步:转流→filter筛选→collect收集;不修改原集合,延迟执行,需终端操作才生效,新手需防null、勿在lambda中做副作用操作。

Java 初学者用 Stream API 过滤集合,核心就三步:转成流 → 写条件 → 收集成新集合。它不改原数据,也不立即执行,得走到最后一步才真正干活。
第一步:把集合变成 Stream
几乎所有集合都能调用 stream() 方法转成流:
-
List
list = Arrays.asList("a", "bb", "ccc");
→ list.stream() -
Set
set = new HashSet(Arrays.asList(1,2,3));
→ set.stream() - 数组要稍不同:Arrays.stream(new int[]{1,2,3}) 或 Stream.of("x","y")
第二步:用 filter() 写筛选条件
filter 接收一个 Predicate(就是返回 true/false 的逻辑),常用写法是 lambda 表达式:
- 数字大于 5:n -> n > 5
- 字符串非空且长度超 2:s -> s != null && !s.trim().isEmpty() && s.length() > 2
- 对象属性判断(比如 User 有 age 和 active 字段):u -> u.getAge() >= 18 && u.isActive()
注意:多个 filter 链起来(如 .filter(...).filter(...))等价于用 && 合并,但分写更清晰;别在 lambda 里打印或改变量——那是副作用,会出问题。
立即学习“Java免费学习笔记(深入)”;
在调试 Java 后端 API 故障时使用此技能,尤其适用于以下任务:分析日志、跨 Controller、Service 和 Mapper 层追踪请求、定位异常根因、检查 SQL 执行或参数流转,以及生成简洁的诊断结论与修复方案。
第三步:用 collect() 拿到结果
filter 只是“准备动作”,必须加终端操作才会执行。最常用的是 collect(Collectors.toList()):
- list.stream().filter(x -> x.startsWith("A")).collect(Collectors.toList())
- 想转成 Set:.collect(Collectors.toSet())
- 只数有多少个:.count()(返回 long)
- 只要第一个匹配项:.findFirst().orElse(null)
别漏掉这步,否则代码白写——filter 不执行,也不报错,只是“没反应”。
几个新手容易踩的坑
写对了语法,结果却不对?多半掉进这些坑里了:
- 忘了防 null:比如 s -> s.toUpperCase() 遇到 null 就崩,得先 s -> s != null && s.length() > 0
- 以为原集合被改了:filter 后原 list 完全不变,所有结果都来自 collect 新建的集合
- 小集合硬套 Stream:5 个元素的列表,用 for 循环更直白、更快;Stream 优势在逻辑清晰和大数据量处理
- filter 里做 IO 或日志:既慢又不可靠,并行流下可能乱序、重复甚至丢数据
记住:filter 是纯函数,只管“要不要这个元素”,别的事交给 map、forEach 或单独的业务代码去做。

















