最常用且最安全的方式是使用stream().filter(),它声明式过滤、不修改原集合、需collect()获取结果,null时应先判空;就地删除用removeIf()或Iterator.remove();Map过滤需先转entrySet()。

用 stream().filter() 是最常用也最安全的方式
Java 8 引入的 Stream API 让集合过滤变得声明式且不易出错。它不会修改原集合,返回的是新集合,适合绝大多数场景。
-
filter()接收一个Predicate,比如x -> x > 10或Objects::nonNull - 链式调用后必须用
collect()才能得到结果,漏掉会报编译错误:java.util.stream.ReferencePipeline$Head cannot be cast to java.util.List - 原始集合为
null时直接调用stream()会抛NullPointerException,建议先判空或用Optional.ofNullable(list).orElse(Collections.emptyList()).stream()...
Listwords = Arrays.asList("apple", "banana", "", "cherry"); List nonEmpty = words.stream() .filter(s -> !s.isEmpty()) .collect(Collectors.toList());
需要就地修改时,用 Iterator.remove() 而不是 for-each
想直接删掉原 List 中不满足条件的元素?千万别在增强 for 循环里调用 list.remove(),会触发 ConcurrentModificationException。
- 必须用
Iterator的remove()方法——它是唯一被允许在遍历时安全删除的途径 -
removeIf()是更简洁的替代(Java 8+),底层就是基于Iterator实现,语义更清晰 - 注意:对
ArrayList多次删除性能较差(涉及数组移动),高频删除建议改用LinkedList或先收集索引再批量删
Listnums = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5)); nums.removeIf(n -> n % 2 == 0); // 删除所有偶数 → [1, 3, 5]
CollectionUtils.filter() 来自 Apache Commons,慎用于新项目
老项目里常见 org.apache.commons.collections4.CollectionUtils.filter(),但它会**就地修改原集合**,且要求传入的 Predicate 必须是 org.apache.commons.collections4.Predicate,和 JDK 的不兼容。
- 如果误传 JDK 的 lambda(如
x -> x > 0),编译不过;强行转型会运行时报ClassCastException - 该方法已标记为
@Deprecated(从 commons-collections4 4.4 开始),官方推荐迁移到 JDK Stream - 若必须用,确保依赖版本 ≥ 4.4,并显式导入
org.apache.commons.collections4.functors.下的谓词类
Map 的过滤不能直接用 filter(),得拆成 keySet / entrySet
Map 本身不是 Collection,没有 stream() 方法(除非转成 entrySet())。常见误区是想直接对 Map 过滤值或键。
立即学习“Java免费学习笔记(深入)”;
- 按 value 过滤:用
map.entrySet().stream().filter(e -> e.getValue() > 100),再collect(Collectors.toMap(...)) - 按 key 过滤:类似,但注意
toMap()的 merge 函数(避免重复 key 报IllegalStateException) - 如果只要过滤后的
keySet或values(),用stream().map(Entry::getKey)或map(Entry::getValue)提取即可
Map实际写的时候,优先选scores = Map.of("Alice", 85, "Bob", 92, "Charlie", 78); Map highScores = scores.entrySet().stream() .filter(e -> e.getValue() >= 90) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
stream().filter();真要改原集合,就用 removeIf();别为了省几行代码引入旧版 Commons 工具类,兼容性和维护成本都高。










