应调用map.entrySet().removeIf(entry -> entry.getValue() == null),因Map接口无removeIf方法;仅适用于可修改的Map实现,ConcurrentHashMap线程安全,普通HashMap多线程下仍可能抛ConcurrentModificationException。

用 removeIf 直接过滤 Map 中 value 为 null 的项
Java 8+ 的 HashMap 等可变集合支持 removeIf,但注意:必须作用于 entrySet(),不能直接对 Map 调用(Map 接口本身没这个方法)。调用后原 Map 被就地修改,无需新建对象。
- 错误写法:
map.removeIf(...)→ 编译失败,Map没该方法 - 正确入口:
map.entrySet().removeIf(entry -> entry.getValue() == null) - 仅适用于支持修改的 Map 实现(如
HashMap、LinkedHashMap),Collections.unmodifiableMap会抛UnsupportedOperationException - 如果 Map 是
ConcurrentHashMap,removeIf是线程安全的;但普通HashMap在遍历时被其他线程修改,仍可能触发ConcurrentModificationException
entrySet() 遍历中调用 remove() 的风险
手动遍历 entrySet() 并在循环里调用 Iterator.remove() 是可行的,但极易出错。常见错误是用增强 for 循环 + map.remove(key),这会导致 ConcurrentModificationException。
- 安全写法:
Iterator<Map.Entry<K, V>> it = map.entrySet().iterator(); while (it.hasNext()) { Map.Entry<K, V> entry = it.next(); if (entry.getValue() == null) { it.remove(); // 必须用迭代器自己的 remove } } - 危险写法:
for (Map.Entry<k> e : map.entrySet()) { if (e.getValue() == null) map.remove(e.getKey()); }</k>→ 运行时报错 - 性能上,
removeIf和手动Iterator.remove()底层都是单次遍历,无本质差异;但前者更简洁,不易漏掉it.remove()
Value 为 null 的判定要小心类型和语义
不是所有 “空” 都等于 null。比如 Optional.empty()、空字符串、空集合、数值 0,都可能被业务视为“无效值”,但它们不触发 entry.getValue() == null。
- 如果目标是过滤“逻辑上为空”的值,需自定义判断逻辑,例如:
entry.getValue() == null || "".equals(entry.getValue()) - 泛型擦除下,
entry.getValue()返回的是Object,若 value 是基本类型包装类(如Integer),== null判定依然有效 - 注意
HashMap允许 key 或 value 为null,但TreeMap的 key 不能为null(否则NullPointerException),不过 value 仍可为null
想保留原 Map 不变?别用 removeIf,改用 stream().filter()
removeIf 是破坏性操作。如果需要生成新 Map 而不改动原数据,必须用流式构造,且注意 Collectors.toMap 对重复 key 的处理策略。
立即学习“Java免费学习笔记(深入)”;
- 基础写法:
Map<K, V> filtered = map.entrySet().stream() .filter(entry -> entry.getValue() != null) .collect(Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue )); - 若原始 Map 的 key 可能重复(比如经过转换),需显式指定 merge 函数,否则抛
IllegalStateException - 流式方式天然线程安全(无副作用),适合函数式风格;但有额外对象开销,大数据量时比
removeIf稍慢 - 注意:
toMap默认返回HashMap,不保留插入顺序;如需有序,得用LinkedHashMap::new作为第三个参数
new HashMap(map) 再 removeIf,其实没必要——除非你明确需要副本。真正容易被忽略的是:removeIf 对不可变 Map 失效,而报错信息只说“不支持操作”,不会提醒你源头是不是 unmodifiableMap。










