ArrayList和LinkedList可存null;HashMap允一个null键和多个null值,Hashtable完全禁止;HashSet和LinkedHashSet允许null,TreeSet无参构造时禁止null,自定义Comparator可支持;ConcurrentHashMap禁止null键值,CopyOnWriteArrayList允许null。

ArrayList 和 LinkedList 能否存 null
可以,ArrayList 和 LinkedList 都允许任意数量的 null 元素。它们底层基于数组或链表实现,不校验元素是否为 null。
常见错误现象:调用 get() 返回 null 后直接链式调用方法(如 list.get(i).toString()),触发 NullPointerException —— 这不是集合本身的问题,而是业务逻辑未判空。
-
add(null)正常执行,不会抛异常 -
contains(null)返回true(如果确实添加过) -
indexOf(null)返回第一个null的下标
HashMap 和 Hashtable 对 null 的处理差异
HashMap 允许一个 null 键和任意多个 null 值;Hashtable 则完全禁止 null 键和 null 值,否则立即抛 NullPointerException。
原因在于 Hashtable 是遗留类,设计时强调线程安全与严格校验;HashMap 更注重灵活性与性能,把判空责任交给使用者。
立即学习“Java免费学习笔记(深入)”;
-
new HashMap().put(null, "a")✅ 成功 -
new Hashtable().put(null, "a")❌ 抛NullPointerException -
new HashMap().put("k", null)✅ 成功 -
new Hashtable().put("k", null)❌ 同样抛异常
HashSet、TreeSet、LinkedHashSet 的 null 支持边界
HashSet 和 LinkedHashSet 允许存 null(因为底层是 HashMap,null 作为 key 存入);TreeSet 是否允许取决于其构造方式:
- 无参构造:使用自然排序,
add(null)直接抛NullPointerException(因为null.compareTo(...)不合法) - 传入自定义
Comparator:若该比较器能安全处理null(例如用Comparator.nullsFirst()),则可存null
注意:TreeSet 中即使允许 null,也只能有一个 —— 因为它按“相等”逻辑去重,而 null 与 null 视为重复。
ConcurrentHashMap 和 CopyOnWriteArrayList 的 null 约束
ConcurrentHashMap 明确禁止 null 键和 null 值,否则在 put() 时就抛 NullPointerException;CopyOnWriteArrayList 允许 null,行为同 ArrayList。
这是并发容器的主动防御设计:ConcurrentHashMap 内部大量依赖 key.hashCode() 和 key.equals(),而 null 会导致这些调用失败或语义模糊,所以从源头拦截。
-
new ConcurrentHashMap().put(null, "v")❌ 立即报错 -
new CopyOnWriteArrayList().add(null)✅ 允许 -
Collections.synchronizedSet(new HashSet())允许null(同步包装不改变底层行为)
Map实际编码中,最容易被忽略的是map = new ConcurrentHashMap<>(); // 下面这行会抛 NullPointerException,不是运行时偶然,而是设计强制 map.put(null, "value"); // java.lang.NullPointerException
TreeSet 的自然排序场景下对 null 的静默拒绝,以及 ConcurrentHashMap 对 null 的零容忍 —— 它们不像 HashMap 那样“宽容”,出错位置也更靠前。










