HCRM博客

为什么CurrentHashMap会报错?

在Java编程中,ConcurrentHashMap和HashtaBLe等线程安全的集合不允许插入null值的key或value,而HashMap则允许,这种设计差异引发了许多开发者的困惑与报错,以下是详细解释:

ConcurrentHashMap 与 Null 值

为什么CurrentHashMap会报错?-图1
(图片来源网络,侵权删除)

1、源码分析:在ConcurrentHashMap的源码中,添加元素的方法put在第一行就进行了判断,如果key值为null或者是value值为null,就直接抛出空指针异常NullPointerException,这是导致插入null值时报错的直接原因。

2、设计原因:ConcurrentHashMap的设计者Doug Lea在邮件回复中提到,这样设计的主要目的是避免在并发场景下出现歧义问题,如果允许null值,那么当查询一个不存在的key时,返回null可能意味着该key确实不存在,也可能意味着该key存在但其对应的value是null,在单线程环境下,可以通过其他方法如containsKey来区分这两种情况,但在多线程环境下,这种二义性问题无法解决。

3、二义性问题:在多线程环境下,如果一个线程查询某个key是否存在,另一个线程在该查询完成之前插入了一个null值,那么查询结果就会变得不可预测,为了避免这种情况,ConcurrentHashMap直接禁止了null值的插入。

4、性能考虑:虽然禁止null值插入可能会在某些情况下增加代码复杂度,但这也避免了在并发环境下可能出现的复杂逻辑和潜在的bug。

5、替代方案:如果确实需要在ConcurrentHashMap中存储null值,可以考虑使用特殊的标记对象,如new Object(),或者使用支持null值的其他数据结构。

常见疑问解答

为什么CurrentHashMap会报错?-图2
(图片来源网络,侵权删除)

问题一:为什么HashMap允许插入null值而ConcurrentHashMap不允许?

答案:HashMap是单线程环境下使用的集合,它允许插入null值,因为在单线程环境下,即使查询到了null值,我们也可以通过hashMap.containsKey(key)的方法来区分这个null值到底是存入的null还是压根不存在的null,从而解决了二义性问题,而ConcurrentHashMap是多线程环境下使用的集合,由于多线程环境的复杂性,我们无法判断某一个时刻返回的null值到底是值为null还是压根就不存在,也就是二义性问题不可被证伪,所以ConcurrentHashMap在源码中直接杜绝了key或value为null的歧义问题。

问题二:如何在ConcurrentHashMap中存储null值?

答案:由于ConcurrentHashMap不允许直接插入null值,因此需要采取一些替代方案来存储null值,一种常见的方法是使用特殊的标记对象来表示null值,可以使用new Object()作为标记对象来表示null值,也可以考虑使用其他支持null值的数据结构来代替ConcurrentHashMap,需要注意的是,在使用这些替代方案时,需要确保它们能够满足程序的需求,并且不会引起其他问题。

为什么CurrentHashMap会报错?-图3
(图片来源网络,侵权删除)

本站部分图片及内容来源网络,版权归原作者所有,转载目的为传递知识,不代表本站立场。若侵权或违规联系Email:zjx77377423@163.com 核实后第一时间删除。 转载请注明出处:https://blog.huochengrm.cn/gz/4598.html

分享:
扫描分享到社交APP
上一篇
下一篇