为什么ConcurrentHashMap中key不允许为null?(美团)

JustJavaIt / 2023-05-09 / 原文

  Doug Lea 是 Java 并发编程领域的知名专家,他曾经是 Java 并发包的主要设计者之一,也是 Java 并发编程的重要贡献者。对于 ConcurrentHashMap 不允许插入 null 值的问题,有人问过  Doug Lea,以下是他回复的邮件内容:

1 The main reason that nulls aren't allowed in ConcurrentMaps (ConcurrentHashMaps, ConcurrentSkipListMaps) is that ambiguities that may be just barely tolerable in non-concurrent maps can't be accommodated. The main one is that if map.get(key) returns null, you can't detect whether the key explicitly maps to null vs the key isn't mapped.In a non-concurrent map, you can check this via map.contains(key),but in a concurrent one, the map might have changed between calls.
2 
3 Further digressing: I personally think that allowingnulls in Maps (also Sets) is an open invitation for programsto contain errors that remain undetected untilthey break at just the wrong time. (Whether to allow nulls evenin non-concurrent Maps/Sets is one of the few design issues surroundingCollections that Josh Bloch and I have long disagreed about.)
4 
5 It is very difficult to check for null keys and valuesin my entire application .Would it be easier to declare somewherestatic final Object NULL = new Object();and replace all use of nulls in uses of maps with NULL?
View Code

  ConcurrentMap(如ConcurrentHashMap、ConcurrentSkipListMap)不允许使用null值的主要原因是,在非并发的Map中(如HashMap),是可以容忍模糊性(二义性)的,而在并发Map中是无法容忍的。假如说,所有的Map都支持null的话,那么map.get(key)就可以返回null,但是,这时候就会存在一个不确定性,当你拿到null的时候,你是不知道他是因为本来就存了一个null进去还是说就是因为没找到而返回了null。在HashMap中,因为它的设计就是给单线程用的,所以当我们map.get(key)返回null的时候,我们是可以通过map.contains(key)检查来进行检测的,如果它返回true,则认为是存了一个null,否则就是因为没找到而返回了null。但是,像ConcurrentHashMap,它是为并发而生的,它是要用在并发场景中的,当我们map.get(key)返回null的时候,是没办法通过通过map.contains(key)检查来准确的检测,因为在检测过程中可能会被其他线程锁修改,而导致检测结果并不可靠。
所以,为了让ConcurrentHashMap的语义更加准确,不存在二义性的问题,他就不支持null。