Java中HashMap和Hashtable之间的区别是什么?

对于非线程应用程序,哪个更有效?


当前回答

注意,很多答案都表明Hashtable是同步的。在实践中,这几乎不会给你带来什么好处。同步是在访问器/赋值器上进行的。方法将停止同时从映射中添加或删除两个线程,但在现实世界中,您通常需要额外的同步。

一个非常常见的习惯用法是“先检查后放”,即在Map中查找条目,如果它不存在,则添加它。无论使用Hashtable还是HashMap,这都不是原子操作。

可通过以下方式获得等效同步的HashMap:

Collections.synchronizedMap(myMap);

但要正确实现此逻辑,您需要以下形式的额外同步:

synchronized(myMap) {
    if (!myMap.containsKey("tomato"))
        myMap.put("tomato", "red");
}

即使迭代Hashtable的条目(或Collections.synchronizedMap获得的HashMap)也不是线程安全的,除非您还通过额外的同步来防止Map被修改。

ConcurrentMap接口(例如ConcurrentHashMap)的实现通过包括线程安全检查然后动作语义(如:

ConcurrentMap.putIfAbsent(key, value);

其他回答

注意,很多答案都表明Hashtable是同步的。在实践中,这几乎不会给你带来什么好处。同步是在访问器/赋值器上进行的。方法将停止同时从映射中添加或删除两个线程,但在现实世界中,您通常需要额外的同步。

一个非常常见的习惯用法是“先检查后放”,即在Map中查找条目,如果它不存在,则添加它。无论使用Hashtable还是HashMap,这都不是原子操作。

可通过以下方式获得等效同步的HashMap:

Collections.synchronizedMap(myMap);

但要正确实现此逻辑,您需要以下形式的额外同步:

synchronized(myMap) {
    if (!myMap.containsKey("tomato"))
        myMap.put("tomato", "red");
}

即使迭代Hashtable的条目(或Collections.synchronizedMap获得的HashMap)也不是线程安全的,除非您还通过额外的同步来防止Map被修改。

ConcurrentMap接口(例如ConcurrentHashMap)的实现通过包括线程安全检查然后动作语义(如:

ConcurrentMap.putIfAbsent(key, value);

HashTable是jdk中的一个遗留类,不应再使用。将其用法替换为ConcurrentHashMap。如果您不需要线程安全,请使用HashMap,它不是线程安全的,但速度更快,占用的内存更少。

HashMap是一个用于以键和值格式存储元素的类。它不是线程安全的。因为它不同步。其中as Hashtable是同步的。Hashmap允许null,但hastable不允许null。

看看这个图表。它提供了不同数据结构之间的比较以及HashMap和Hashtable。比较准确、清晰且易于理解。

Java集合矩阵

HashTable和HashMaps有5个基本区别。

映射允许您迭代和检索键、值以及两个键-值对,而HashTable不具备所有这些功能。Hashtable中有一个函数contains(),使用起来非常混乱。因为contains的意思稍有偏差。它是指包含键还是包含值?很难理解。在Maps中,我们有ContainsKey()和ContainsValue()函数,这两个函数非常容易理解。在hashmap中,您可以在迭代时安全地删除元素。因为这在哈希表中是不可能的。HashTables默认情况下是同步的,因此可以轻松地与多个线程一起使用。默认情况下,as HashMaps不同步,因此只能用于单个线程。但您仍然可以使用Collections-util类的synchronizedMap(Mapm)函数将HashMap转换为synchronized。HashTable不允许空键或空值。其中作为HashMap允许一个空键和多个空值。