【问题标题】:Issue with null elements with synchronized and concurrent collection [duplicate]具有同步和并发集合的空元素问题[重复]
【发布时间】:2013-03-31 16:31:14
【问题描述】:

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

【问题讨论】:

  • 你的答案在这里 ;) stackoverflow.com/questions/7556357/…
  • @Mik378 我已经通过上面的讨论了。这个讨论都是关于关键的。但在这里我也在寻找为什么在同步和并发集合中不允许空值。
  • ok :) 你应该在你的帖子标题中精确说明

标签: java collections concurrency synchronization


【解决方案1】:

Hashtable 有点过时了,所以我不会评论它。至于ConcurrentHashMap,与标准HashMap 相比,API 的重要补充之一是一些原子方法,例如putIfAbsent。 Javadoc:

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

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

另请参阅this postthese comments by the author of CHM

【讨论】:

    【解决方案2】:

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

    1. 哈希表中不存在该键
    2. 键存在,但设置的值为空

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

    【讨论】:

    • 这同样适用于允许空值的 HashMap。
    【解决方案3】:

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

        Map m = Collections.synchronizedMap(new HashMap());
    

    【讨论】:

    • 感谢您的回复,但在这里您要手动同步。但我正在寻找为什么它不是同步和并发集合的默认性质。
    【解决方案4】:

    来自 Hashtable JavaDoc:

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

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

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

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

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

    来源:Why does Hashtable not take null key?

    【讨论】:

    • 为什么哈希表不允许空值?
    • "要成功地从哈希表中存储和检索对象,用作键的对象必须实现 hashCode 方法和 equals 方法。"
    【解决方案5】:

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

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

    Null 没有附加任何值,它只是意味着没有对象。所以为了避免歧义,最好不要有它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-14
      • 2017-10-08
      • 1970-01-01
      • 1970-01-01
      • 2013-04-17
      • 1970-01-01
      相关资源
      最近更新 更多