为什么Hashtable不允许空键或值?

4,804 阅读2分钟

Hashtable和ConcurrentHashMap不允许空键或值的主要原因是期望它们将在多线程环境中使用。一分钟,让我们假设允许空值。在这种情况下,get方法具有模糊行为。如果在映射中找不到键,则它可以返回null;如果找到键并且其值为null,则它可以返回null。当代码需要空值时,它通常会检查映射中是否存在密钥,以便它可以知道密钥是否存在或密钥是否存在但值为null。现在这个代码在多线程环境中中断了。我们来看看下面的代码:

if (map.contains(key)) {
    return map.get(key);
} else {
    throw new KeyNotFoundException;
}

在上面的代码中,假设线程t1调用contains方法并找到密钥,它假定密钥存在并准备好返回值,无论它是否为null。在调用map.get之前,另一个线程t2从地图中删除该键。现在t1恢复并返回null。但是根据代码,t1的正确答案是KeyNotFoundException,因为该键已被删除。但它仍然返回null,因此预期的行为被打破。

现在,对于常规的HashMap,假设它将被单个线程调用,因此在“包含”检查和“获取”的中间不可能删除密钥。因此HashMap可以容忍空值。但是对于Hashtable和ConcurrentHashMap,期望很明显,多个线程将对数据进行操作。因此,他们不能允许空值并给出错误的答案。键的逻辑也是一样的。现在,counter参数可以是 - 对于Hashtables和ConcurrentHashMaps的非空值,contains和get步骤可能会失败,因为另一个线程可以在执行第二步之前修改map / table。这是正确的,它可能发生。但由于Hashtables和ConcurrentHashMaps不允许使用null键和值,他们没有必要首先实现包含和检查。他们可以直接获取值,因为他们知道如果get方法返回null,唯一的原因是键不存在而不是因为值可能为null。只有HashMaps才需要包含和获取检查,因为它们允许空值,因此需要解决关于是否找不到键或值为空的歧义。

HashTable类是在散列机制上实现的,这意味着存储任何键值对,它是键对象的必需哈希码。如果key为null,则无法给出散列,它将通过空指针异常和类似值的情况,如果值为null,则抛出null。