Java中用Lambda配合removeIf可一行删除集合元素,其核心是传入Predicate谓词实现原地过滤,支持ArrayList、HashSet等但不支持Arrays.asList()返回的不可变视图,需注意避免并发修改异常和性能陷阱。

Java 中用 Lambda 表达式配合 removeIf 删除集合元素,核心是把删除条件写成简洁的函数式逻辑,一行搞定批量过滤。
removeIf 的作用和基本用法
removeIf 是 Collection 接口定义的方法(JDK 8+),它接收一个 Predicate 参数,遍历集合,对每个元素执行该谓词,返回 true 的元素会被原地移除。它内部自动处理并发修改问题,无需手动迭代或使用迭代器的 remove()。
例如:
list.removeIf(x -> x % 2 == 0); // 删除所有偶数
常见集合类型支持情况
以下集合可直接调用 removeIf:
- ArrayList / LinkedList:完全支持,效率取决于底层实现(ArrayList 遍历快,删除需移动;LinkedList 删除快但遍历慢)
-
HashSet / LinkedHashSet / TreeSet:支持,但注意
TreeSet的谓词不能改变比较逻辑,否则行为未定义 - CopyOnWriteArrayList:支持,适合多线程读多写少场景,但每次删除都会复制数组,慎用于大集合
-
Arrays.asList() 返回的 List:支持,但底层是固定大小数组包装,删除后实际会抛
UnsupportedOperationException—— 因为它是不可变结构的视图
实用删除场景与 Lambda 写法
关键在于把“什么该删”准确表达为 Predicate:
-
按属性值删除:
users.removeIf(u -> u.getAge() -
按字符串匹配删除:
names.removeIf(s -> s.startsWith("test") || s.isEmpty()); -
按引用或 null 判断删除:
list.removeIf(Objects::isNull);或list.removeIf(s -> s != null && s.trim().length() == 0); -
组合条件(推荐提取方法引用或局部变量):
String prefix = "tmp_";<br>files.removeIf(f -> f.getName().startsWith(prefix) && !f.isDirectory());
注意事项和避坑点
看似简单,但几个细节容易出错:
-
不能在 Lambda 中修改当前集合本身(比如再调一次
removeIf或add),会导致ConcurrentModificationException(尽管不是多线程) -
对 Map 的 value 集合可用,key 集合也可用,但 entrySet 不建议直接删 key;如需按 key 删除,用
map.keySet().removeIf(k -> k.startsWith("old")); -
Stream.filter + collect 是非破坏性操作,如果不想改原集合,就别用
removeIf,改用:List<user> filtered = list.stream()<br> .filter(u -> u.getAge() >= 18)<br> .collect(Collectors.toList());</user>
- 性能敏感时注意装箱/重复计算:避免在 Lambda 中反复调用开销大的方法,可提前缓存结果
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











