HashMap允许一个null键是设计使然,通过if(key==null)分支直接存到table[0]避免NPE;因==判定所有null键相等,故仅允许一个;而null值不受限。
HashMap的null键是设计使然,不是bug
Java的
明确允许一个
键,这是JDK源码里写死的行为,不是疏漏。它的
和
方法对
做了特殊处理:当键为
时,不走常规哈希计算,而是直接存到数组索引0的位置(即
)。这避免了
抛
。
关键点在于:
内部用
分支单独处理,而不是依赖
或
——所以即使
没有哈希值,也能安全插入和查找。
为什么只允许一个null键,但允许多个null值
因为
的键必须唯一,而
键的“相等性”由
判定:所有
键都视为同一个键。所以第二次
会覆盖第一次的value,不会新增Entry。
→ 插入成功
→ 不新增节点,只更新value为"b"
→ 完全合法,value可以是任意
对象
换句话说:键的唯一性约束作用于
本身,而value只是普通引用,不受限制。
立即学习
“
Java免费学习笔记(深入)
”;
Eclipse导入Android或其他的JAVA项目的正确方法 WORD版
本文档主要讲述的是Eclipse导入Android或其他的JAVA项目的正确方法;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看
下载
与HashTable、ConcurrentHashMap对比时要注意空指针风险
和
完全禁止
键和
值,调用
会立即抛
。这不是性能考虑,而是线程安全实现的需要——它们无法像
那样在单线程下用简单分支兜底。
常见踩坑场景:
把
换成
做并发改造时,没检查原有
键逻辑,运行时报错
工具类接收
参数,假设能接受
键,结果传入
实例导致崩溃
在
中可能误判:返回
未必代表键不存在,也可能是value被显式设为
实际编码中如何安全使用null键
除非业务逻辑明确依赖“存在一个默认配置项”,否则尽量避免用
作键。它会让代码可读性和可维护性下降,尤其在debug时难以区分“没找到”和“找到了但值为空”。如果真要用,务必配合注释和防御性判断:
更稳妥的做法是用一个专用哨兵对象,比如
——这样既保持语义清晰,又避开
带来的歧义和兼容性问题。
HashMapnullputgetnullnulltable[0]null.hashCode()NullPointerExceptionHashMapif (key == null)hashCode()equals()nullHashMapnull==nullput(null, value)put(null, "a")put(null, "b")put("k", null)nullnullHashTableConcurrentHashMapnullnullput(null, v)NullPointerExceptionHashMapHashMapConcurrentHashMapnullMapnullHashTableObjects.requireNonNull(map.get(key))HashMapnullnullnullmap.put(null, defaultConfig); // 表示全局默认配置
// 后续获取时不能只靠 == null 判断是否存在
if (map.containsKey(null)) {
Config cfg = map.get(null);
}private static final Object DEFAULT_KEY = new Object();null