1

大多数同步和并发集合(如 HashTable、ConcurrentHashMap 等)都不允许空值。空元素有什么具体问题吗?

4

5 回答 5

1

HashTable.get(key)如果指定的键不存在于 HashTable 中,则方法返回 null。如果 HashTable 允许null作为值,则如果我从HashTable.get(key)方法中获取 null,则可能有两种可能性。

  1. 哈希表中不存在密钥
  2. 键存在,但值集为空

API 的用户可能会感到困惑。我相信他们不允许空值只是为了防止这种歧义。

于 2013-03-31T17:12:00.053 回答
1

Hashtable 有点过时,所以我不会对此发表评论。至于ConcurrentHashMapAPI 与标准的重要补充之一HashMap是一些原子方法,例如putIfAbsent. Java 文档:

返回与指定键关联的前一个值,如果该键没有映射,则返回 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)) {
}

并发环境中的问题是整个事情不是原子的。

另见这篇文章CHM 作者的这些评论

于 2013-03-31T18:12:33.007 回答
0

这是一个接受空键和值的同步映射

    Map m = Collections.synchronizedMap(new HashMap());
于 2013-03-31T16:35:46.280 回答
0

从哈希表 JavaDoc:

要成功地从哈希表中存储和检索对象,用作键的对象必须实现 hashCode 方法和 equals 方法。

简而言之,由于 null 不是对象,因此您不能对其调用 .equals() 或 .hashCode() ,因此 Hashtable 无法计算哈希以将其用作键。

HashMap 较新,并且具有更高级的功能,基本上只是对 Hashtable 功能的改进。因此,在创建 HashMap 时,它专门设计为将 null 值作为键处理,并将它们作为特殊情况处理。

具体来说,在发出 .get(key) 时,使用 null 作为键的处理方式如下:

(key==null ? k==null : key.equals(k))

资料来源:为什么 Hashtable 不采用空键?

于 2013-03-31T16:43:47.480 回答
0

当您同步时,这意味着您将获得对该对象或某个部分的锁定。如果您的对象为空,那么您将如何决定您将在哪个部分获得锁定?

说在concurrenthashmaps中,你可以把它分成16个不同的锁。现在你将如何决定将 null 放置在哪里?

Null 没有附加值,它只是意味着没有对象。因此,为了避免歧义,最好不要拥有它。

于 2013-03-31T17:11:46.943 回答