首先我们先运行一个例子来分析
从例子中可以发现,hashmap毋庸置疑可以存储null键值对,hashtable和ConcurrentHashMap不可以存储null键值对,并且null值,null也不可以单独存储,其原因剖析源码如下:
1.HashTalble
2.ConcurrentHashMap
从分析中我们可以看到,hashtable,对于null值会抛出异常,而对于null键,则会调用null.hashCode(),而导致空指针异常,而concurrenthashmap则对于null键值对,直接抛出空异常,这也就是为什么他们存入null键值对抛出异常的原因.那么我们看看hashmap又是怎么做到存储null键值对
从上图我们可以看出对于key,它调用了hash方法,在其中对于null值,赋予了0值处理,对于null键,他直接存入了Node对象未进行任何处理,所以综上可以存储null键值对,但只能有一个null键,可以存入多个null值,要求其对应的key不同.
那么我就开始思考,为什么这样设计呢?后来翻阅很多资料和分析得出这样一个我个人觉得比较合理的结论:
ConcurrentHashmap和Hashtable都是线程安全用来做支持并发的,这样会有一个问题,当你通过get(k)获取对应的value时,如果获取到的是null时,你无法判断,它是put(k,v)的时候value为null,还是这个key从来没有做过映射。而HashMap是非并发的,可以通过contains(key)来做这个判断。而支持并发的Map在调用m.contains(key)和m.get(key),m很可能已经不同了