大多数同步和并发集合(如HashTable,ConcurrentHashMap等)不允许空值。 null元素是否有任何特定问题?
答案 0 :(得分:1)
HashTable.get(key)
方法返回null。如果HashTable允许null
作为值,那么如果我从HashTable.get(key)
方法获得null,则有两种可能性。
API的用户可能会感到困惑。 我相信他们不允许空值只是为了防止这种歧义。
答案 1 :(得分:1)
Hashtable有点过时,所以我不会评论它。对于ConcurrentHashMap
,API与标准HashMap
的重要补充之一是一些原子方法,例如putIfAbsent
。的Javadoc:
返回与指定键关联的先前值,如果没有键的映射
,则返回null
特别是,如果地图允许使用null键,则使用该方法会更复杂。您需要确保无法覆盖值的典型模式是:
ConcurrentMap<K,V> map = new ConcurrentHashMap<> ();
V value = map.get(key);
if (value == null) {
value = new V();
V previousValue = map.putIfAbsent(key, value);
if (previousValue != null) { //Here you need to be sure what that means
value = previousValue;
}
}
useValue(value);
另一个例子是你如何检查一个键是否在HashMap中(并且你需要返回值):
V value = map.get(key);
if (value == null && !map.containsKey(key)) {
}
并发环境中的问题是整个事情不是原子的。
答案 2 :(得分:0)
这是一个接受空键和值的同步映射
Map m = Collections.synchronizedMap(new HashMap());
答案 3 :(得分:0)
来自Hashtable JavaDoc:
要成功存储和检索哈希表中的对象, 用作键的对象必须实现hashCode方法和 等于方法。
简而言之,由于null不是对象,因此无法调用.equals()或 .hashCode()就可以了,所以Hashtable无法计算哈希来使用它 一把钥匙。
HashMap更新,并且具有更多高级功能 基本上只是对Hashtable功能的改进。因此, 在创建HashMap时,它专门用于处理null 将值作为键并将其作为特殊情况处理。
具体来说,使用null作为键是这样处理的 发出.get(密钥):
(key == null?k == null:key.equals(k))
答案 4 :(得分:0)
同步时,意味着您将获得该对象或某个部分的锁定。如果您的对象为null,那么您将如何决定在哪个部分获得锁定?
在concurrenthashmaps中说,你可以把它分成16个不同的锁。现在您将如何确定将放置null的位置?
Null没有附加值,它只是意味着没有对象。所以为了避免歧义,最好不要拥有它。