getordefault更安全高效:避免并发竞态和重复查找,但需注意默认值共享、concurrenthashmap弱一致性及null限制。

getOrDefault 为什么比先 containsKey 再 get 更安全
直接用 getOrDefault 可以避免并发场景下 key 被其他线程删掉导致的空指针——containsKey 和 get 是两次独立操作,中间存在竞态窗口。即使单线程,也少写两行判断,逻辑更紧凑。
注意:它只适用于 Map 接口的实现类(如 HashMap、ConcurrentHashMap),不适用于 Properties 或自定义 Map 包装类(除非显式重写了该方法)。
默认值是 null 还是 new 实例?关键看场景
传入的默认值对象会被直接返回,不会自动克隆或延迟初始化。如果默认值是可变对象(比如 new ArrayList()),多次调用 getOrDefault 会返回同一个实例引用,可能引发意外共享修改。
- 需要每次返回新对象 → 改用
computeIfAbsent(key, k -> new ArrayList()) - 默认值是不可变类型(
"N/A"、0、Boolean.FALSE)→ 直接传没问题 - 不确定是否被修改过 → 用
getOrDefault(key, Collections.emptyList())比new ArrayList()更安全
和 get() + 三元运算符比,性能差在哪
getOrDefault 底层仍是调用一次 get,没有额外哈希查找,性能几乎等同于 map.get(key) != null ? map.get(key) : defaultValue,但后者会查两次键(一次判空、一次取值),实际慢约 1.5–2 倍(尤其在大 Map 中)。
不过要注意:如果默认值构造开销大(比如解析 JSON 字符串),而 key 大概率存在,那还是先 get 判空再手动处理更合适,避免无谓初始化。
ConcurrentHashMap 的 getOrDefault 有陷阱
在 ConcurrentHashMap 中,getOrDefault 是弱一致性操作:它不阻止其他线程同时 remove 或 replace 该 key,所以返回的默认值不代表“此刻 key 绝对不存在”,只代表“本次查找没找到”。这和业务上“严格不存在”不是一回事。
如果逻辑依赖“key 真的没被设过”,得配合锁或 computeIfAbsent + 显式状态标记来保证。
另外,它的默认值参数不能为 null(会抛 NullPointerException),这点和 HashMap 一致,但容易在迁移代码时忽略。










