Lov*_*ija 33 java hashtable hashmap
如JDK文档中所述,Hashtable不允许使用null键或值.HashMap允许一个空键和任意数量的空值.为什么是这样?
Jai*_*dra 42
Hashtable是较旧的类,通常不鼓励使用它.也许他们看到需要一个null键,更重要的是 - null值,并将其添加到HashMap实现中.
HashMap更新,并且具有更高级的功能,这基本上只是对Hashtable功能的改进.创建HashMap时,它专门设计为将空值作为键处理并将其作为特殊情况处理.
编辑
来自Hashtable JavaDoc:
要从Hashtable成功存储和检索对象,用作键的对象必须实现hashCode方法和equals方法.
由于null不是对象,因此无法调用.equals()或.hashCode()使用它,因此Hashtable无法计算散列以将其用作键.
小智 6
Hashtable和ConcurrentHashMap不允许空键或值的主要原因是因为期望它们将在多线程环境中使用。一分钟,让我们假设允许空值。在这种情况下,get方法具有不明确的行为。如果在映射中找不到键,则可以返回null;如果找到键并且其值为null,则可以返回null。当代码期望空值时,通常会检查映射中是否存在键,以便它可以知道该键是否不存在或该键是否存在但value为空。现在,此代码在多线程环境中中断。让我们看一下下面的代码:
if (map.contains(key)) {
return map.get(key);
} else {
throw new KeyNotFoundException;
}
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,假设线程t1调用contains方法并找到键,并且假定键存在并且可以返回值(无论它是否为null)。现在,在调用map.get之前,另一个线程t2从地图中删除了该键。现在t1恢复并返回null。但是,根据代码,t1的正确答案是KeyNotFoundException,因为密钥已被删除。但是它仍然返回null,因此预期的行为被破坏了。
现在,对于常规的HashMap,假定它将被单个线程调用,因此在“包含”检查和“获取”过程中不可能删除键。因此HashMap可以容忍null值。但是,对于Hashtable和ConcurrentHashMap,很明显期望多个线程将对数据起作用。因此,他们负担不起允许空值并给出错误的答案。密钥的逻辑相同。现在counter参数可以是-对于Hashtables和ConcurrentHashMaps的非null值,contains和get步骤可能会失败,因为另一个线程可以在执行第二步之前修改映射/表。没错,这有可能发生。但是由于Hashtables和ConcurrentHashMaps不允许使用null键和值,他们不必首先实现包含并获取检查。他们可以直接获取值,因为他们知道如果get方法返回null,则唯一的原因是不存在键,而不是因为值可能为null。包含和获取检查仅对于HashMaps才是必需的,因为它们允许使用null值,因此需要解决关于是否找到键或值是否为null的歧义。