面试记录-哪种Map可以存放null键值,其他的为什么不行?

这是我在面试的时候碰到面试官问到的一个问题;

其实这个问题问的是比较刁钻的,因为要从源码设计的角度去回答这个问题,

首先,允许存在null键值的map集合为HashMap,那么为什么HashTable和ConcurrentMap这两个集合不允许null值呢;

这里上作者的原话:

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.

大致意思是:在单线程环境中,不会存在一个线程操作该 HashMap 时,其他的线程将该 HashMap 修改的情况,可以通过 contains(key)来做判断是否存在这个键值对,从而做相应的处理; 而在多线程环境下,可能会存在多个线程同时修改键值对的情况,这时是无法通过contains(key)来判断键值对是否存在的,这会带来一个二义性的问题,Doug Lea说二义性是多线程中不能容忍的!

也就是说作者在设计HashMap集合之初,就完全没有考虑他的安全性,默认的就是单线程执行的;当key为null进行hash运算的时候采用三目运算,hash值直接返回0; 

源码如下:

而HashTable和ConcurrentMap作为安全的集合,在设计之初是要考虑到线程安全的问题,也就是说有多个线程同时对键值进行修改,那么此时在 使用contains(key)方法的时候就会出现一个歧义,到底是key为null呢,还是说根本不存在null这个key呢,这时候就产生了歧义,所以安全的集合键值都是不能为null的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值