4114

Java中的aHashMap和a有什么区别?Hashtable

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

4

35 回答 35

4079

HashMapJava之间和Java之间有几个区别Hashtable

  1. Hashtable同步的,而HashMap不是。这HashMap对于非线程应用程序来说更好,因为非同步对象通常比同步对象执行得更好。

  2. Hashtable不允许null键或值。 HashMap允许一个null键和任意数量的null值。

  3. HashMap 的子类之一是LinkedHashMap,因此如果您想要可预测的迭代顺序(默认为插入顺序),您可以轻松地HashMapLinkedHashMap. 如果您使用Hashtable.

由于同步对您来说不是问题,因此我建议使用HashMap. 如果同步成为问题,您还可以查看ConcurrentHashMap.

于 2008-09-02T23:02:37.180 回答
754

请注意,许多答案都表明 Hashtable 是同步的。 在实践中,这给你带来的收益很少。 访问器/修改器方法上的同步将停止两个线程同时从映射中添加或删除,但在现实世界中,您通常需要额外的同步。

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

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

Collections.synchronizedMap(myMap);

但是要正确实现此逻辑,您需要对表单进行额外的同步

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

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

接口的实现ConcurrentMap(例如ConcurrentHashMap)通过包含线程安全的 check-then-act 语义来解决其中的一些问题,例如:

ConcurrentMap.putIfAbsent(key, value);
于 2008-09-03T11:00:41.213 回答
404

Hashtable被认为是遗留代码。没有什么Hashtable不能使用HashMap或派生来完成的HashMap,所以对于新代码,我看不出有任何理由回到Hashtable.

于 2009-06-25T01:46:17.853 回答
214

这个问题经常在面试中被问到,以检查候选人是否理解集合类的正确用法以及是否知道可用的替代解决方案。

  1. 该类HashMap大致相当于Hashtable,除了它是非同步的并且允许空值。(HashMap允许空值作为键和值,而Hashtable不允许nulls)。
  2. HashMap不保证地图的顺序会随着时间的推移保持不变。
  3. HashMap是非同步的,Hashtable而是同步的。
  4. 中的迭代器HashMap是故障安全的,而枚举Hashtable器不是,并且ConcurrentModificationException如果任何其他线程通过添加或删除除Iterator自己的remove() 方法之外的任何元素来在结构上修改映射,则抛出异常。但这不是保证行为,JVM 会尽最大努力来完成。

一些重要术语的注意事项:

  1. 同步意味着只有一个线程可以在一个时间点修改哈希表。基本上,这意味着任何线程在对 a 执行更新之前Hashtable都必须获取对象上的锁,而其他线程将等待锁被释放。
  2. 故障安全在迭代器的上下文中是相关的。如果在集合对象上创建了一个迭代器,并且某个其他线程试图“结构化地”修改集合对象,则会引发并发修改异常。其他线程可以调用该set方法,因为它不会“结构地”修改集合。但是,如果在调用之前set,集合已经在结构上进行了修改,IllegalArgumentException则会被抛出。
  3. 结构修改是指删除或插入可以有效改变地图结构的元素。

HashMap可以通过同步

Map m = Collections.synchronizeMap(hashMap);

Map 提供 Collection 视图,而不是通过 Enumeration 对象直接支持迭代。集合视图极大地增强了界面的表现力,这将在本节后面讨论。Map 允许您迭代键、值或键值对;Hashtable不提供第三种选择。Map 提供了一种在迭代过程中删除条目的安全方法;Hashtable没有。Hashtable最后,Map 修复了界面中的一个小缺陷。Hashtable有一个名为 contains 的方法,如果Hashtable包含给定值,则返回 true。鉴于它的名称,如果包含给定的键,您会期望此方法返回 true,Hashtable因为该键是 a 的主要访问机制Hashtable。Map 接口通过重命名方法消除了这种混淆来源containsValue. 此外,这提高了界面的一致性containsValue——parallels containsKey

地图界面

于 2011-10-04T06:39:52.813 回答
146

HashMapMap使用哈希码索引数组的接口实现。 Hashtable: 你好,1998 年打来的。他们希望他们的收藏 API 回来。

不过说真的,你最好完全远离Hashtable。对于单线程应用程序,您不需要额外的同步开销。对于高度并发的应用程序,偏执的同步可能会导致饥饿、死锁或不必要的垃圾收集暂停。就像 Tim Howland 指出的那样,您可以ConcurrentHashMap改用。

于 2008-09-02T23:14:11.333 回答
140

请记住,HashTable在引入 Java 集合框架 (JCF) 之前,它是遗留类,后来被改造以实现Map接口。Vector和 也是如此Stack

因此,在新代码中始终远离它们,因为正如其他人所指出的那样,JCF 中总是有更好的选择。

这是您会发现有用的Java 集合备忘单。请注意,灰色块包含遗留类 HashTable、Vector 和 Stack。

在此处输入图像描述

于 2014-03-25T08:58:01.233 回答
92

已经发布了许多好的答案。我正在添加一些新观点并对其进行总结。

HashMap并且Hashtable两者都用于以键和值形式存储数据。两者都使用散列技术来存储唯一键。但是下面给出的 HashMap 和 Hashtable 类之间存在许多差异。

哈希映射

  1. HashMap是非同步的。它不是线程安全的,如果没有适当的同步代码,就不能在多个线程之间共享。
  2. HashMap允许一个空键和多个空值。
  3. HashMap是 JDK 1.2 中引入的一个新类。
  4. HashMap很快。
  5. 我们可以通过调用此代码使HashMapas 同步
    Map m = Collections.synchronizedMap(HashMap);
  6. HashMap被迭代器遍历。
  7. 迭代器 inHashMap是快速失败的。
  8. HashMap继承 AbstractMap 类。

哈希表

  1. Hashtable是同步的。它是线程安全的,可以与许多线程共享。
  2. Hashtable不允许空键或值。
  3. Hashtable是一个遗留类。
  4. Hashtable是缓慢的。
  5. Hashtable是内部同步的,不能不同步。
  6. Hashtable由 Enumerator 和 Iterator 遍历。
  7. 枚举Hashtable器不是快速失败的。
  8. Hashtable继承字典类。

进一步阅读Java 中的 HashMap 和 Hashtable 有什么区别?

在此处输入图像描述

于 2017-03-06T10:09:44.630 回答
71

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

Java 集合矩阵

于 2012-11-20T05:35:53.423 回答
70

除了 izb 所说的,HashMap允许空值,而Hashtable不允许。

另请注意,作为JavadocsHashtable状态的扩展Dictionary类已过时,已被接口取代。Map

于 2008-09-02T20:30:00.200 回答
53

Hashtable类似于HashMap并且具有类似的界面。建议您使用HashMap,除非您需要对遗留应用程序的支持或您需要同步,因为Hashtables方法是同步的。所以在你的情况下,你不是多线程,HashMaps是你最好的选择。

于 2008-09-02T20:25:30.117 回答
45

Hashtable是同步的,而HashMap不是。这使得HashtableHashmap.

对于单线程应用程序,请使用它们,HashMap因为它们在功能方面是相同的。

于 2008-09-02T20:22:34.023 回答
39

hashtable 和 hashmap 之间的另一个关键区别是 HashMap 中的 Iterator 是快速失败的,而 Hashtable 的枚举器不是,并且如果任何其他线程通过添加或删除除 Iterator 自己的 remove() 方法之外的任何元素在结构上修改映射,则抛出 ConcurrentModificationException。但这不是保证行为,JVM 会尽最大努力完成。”

我的来源:http: //javarevisited.blogspot.com/2010/10/difference-between-hashmap-and.html

于 2011-09-08T06:40:13.040 回答
39

除了这里已经提到的所有其他重要方面之外,Collections API(例如 Map 接口)一直在修改以符合 Java 规范的“最新和最伟大”的补充。

例如,比较 Java 5 Map 迭代:

for (Elem elem : map.keys()) {
  elem.doSth();
}

与旧的 Hashtable 方法相比:

for (Enumeration en = htable.keys(); en.hasMoreElements(); ) {
  Elem elem = (Elem) en.nextElement();
  elem.doSth();
}

在 Java 1.8 中,我们还被承诺能够像在良好的旧脚本语言中一样构造和访问 HashMap:

Map<String,Integer> map = { "orange" : 12, "apples" : 15 };
map["apples"];

更新:不,他们不会登陆 1.8... :(

Project Coin 的收藏增强功能会出现在 JDK8 中吗?

于 2012-01-12T09:17:16.543 回答
32
  • HashTable是同步的,如果你在单线程中使用它,你可以使用HashMap,这是一个非同步版本。未同步的对象通常性能更高一些。顺便说一句,如果多个线程同时访问一个HashMap,并且至少有一个线程在结构上修改了map,那么它必须在外部同步。您可以使用以下方法将未同步的地图包装在同步地图中:

    Map m = Collections.synchronizedMap(new HashMap(...));
    
  • HashTable 只能包含非空对象作为键或值。HashMap 可以包含一个空键和空值。

  • Map 返回的迭代器是快速失败的,如果在创建迭代器后的任何时间对映射进行结构修改,除了通过迭代器自己的 remove 方法之外的任何方式,迭代器都会抛出一个ConcurrentModificationException. 因此,面对并发修改,迭代器快速而干净地失败,而不是在未来不确定的时间冒任意的、非确定性的行为。Hashtable 的键和元素方法返回的枚举不是快速失败的。

  • HashTable 和 HashMap 是Java Collections Framework的成员(从 Java 2 平台 v1.2 开始,HashTable 被改造以实现 Map 接口)。

  • HashTable 被认为是遗留代码,如果需要线程安全的高并发实现,文档建议使用ConcurrentHashMap代替 Hashtable。

  • HashMap 不保证返回元素的顺序。对于 HashTable 我想它是相同的,但我不完全确定,我没有找到明确说明这一点的资源。

于 2012-04-29T13:57:46.600 回答
32

HashMap并且Hashtable在算法上也存在显着差异。以前没有人提到过这一点,所以这就是我提出它的原因。HashMap将构造一个大小为 2 的哈希表,动态增加它,这样您在任何桶中最多有大约八个元素(碰撞),并且对于一般元素类型会很好地搅拌元素。但是,Hashtable如果您知道自己在做什么,则该实现提供了对散列的更好和更精细的控制,即您可以使用最接近您的值域大小的素数来修复表大小,这将导致比 HashMap 更好的性能,即更少的冲突对于某些情况。

与此问题中广泛讨论的明显差异不同,我将 Hashtable 视为“手动驾驶”汽车,您可以更好地控制散列,而 HashMap 作为“自动驾驶”对应物,通常会表现良好。

于 2012-12-10T08:57:14.940 回答
31

根据此处的信息,我建议使用 HashMap。我认为最大的优势是 Java 会阻止您在迭代它时对其进行修改,除非您通过迭代器进行修改。

于 2008-09-02T20:14:53.840 回答
30

A Collection(有时称为容器)只是将多个元素组合成一个单元的对象。Collections 用于存储、检索、操作和通信聚合数据。集合框架W是用于表示和操作集合的统一架构。

HashMap JDK1.2Hashtable JDK1.0,都用于表示<Key, Value>成对表示的一组对象。每<Key, Value>对称为Entry对象。Entries 的集合由 和 的对象HashMap引用Hashtable。集合中的键必须是唯一的或独特的。[因为它们用于检索特定键的映射值。集合中的值可以重复。]


« 超类、遗产和集合框架成员

Hashtable 是 中引入的遗留类JDK1.0,是 Dictionary 类的子类。From JDK1.2Hashtable 被重新设计以实现Map 接口,成为集合框架的成员。HashMap 是 Java 集合框架的成员,从它在JDK1.2. HashMap 是 AbstractMap 类的子类。

public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, Serializable { ... }

public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable { ... }

« 初始容量和负载系数

容量是哈希表中的桶数,初始容量只是哈希表创建时的容量。注意哈希表是开放的:在一个“ hash collision”的情况下,单个桶存储多个条目,必须按顺序搜索。负载因子是哈希表在其容量自动增加之前允许达到的程度的度量。

HashMap 使用默认初始容量(16)和默认加载因子 (0.75) 构造一个空哈希表。其中 Hashtable 构造具有默认初始容量(11)和负载因子/填充率 (0.75) 的空哈希表。

哈希图和哈希表

« 哈希冲突情况下的结构修改

HashMapHashtable在哈希冲突的情况下,它们将映射条目存储在链表中。从 Java8 开始,HashMap如果哈希桶增长超过某个阈值,该桶将从linked list of entries to a balanced tree. 它将最坏情况的性能从 O(n) 提高到 O(log n)。将列表转换为二叉树时,哈希码用作分支变量。如果同一个桶中有两个不同的哈希码,一个被认为更大,在树的右边,另一个在左边。但是当两个哈希码相等时,HashMap假设键是可比较的,并比较键以确定方向,以便可以保持某种顺序。HashMap 制作可比较的键是一个很好的做法。如果存储桶大小达到,则添加条目TREEIFY_THRESHOLD = 8将条目的链表转换为平衡树,删除少于TREEIFY_THRESHOLD 且最多的条目UNTREEIFY_THRESHOLD = 6会将平衡树重新转换为条目的链表。Java 8 SRC

« 集合视图迭代,Fail-Fast 和 Fail-Safe

    +--------------------+-----------+-------------+
    |                    | Iterator  | Enumeration |
    +--------------------+-----------+-------------+
    | Hashtable          | fail-fast |    safe     |
    +--------------------+-----------+-------------+
    | HashMap            | fail-fast | fail-fast   |
    +--------------------+-----------+-------------+
    | ConcurrentHashMap  |   safe    |   safe      |
    +--------------------+-----------+-------------+

Iterator本质上是快速失败的。即,如果在迭代时修改了集合而不是它自己的 remove() 方法,它会抛出 ConcurrentModificationException。asEnumeration本质上是故障安全的。如果在迭代时修改了集合,它不会抛出任何异常。

根据 Java API Docs,Iterator 总是优于 Enumeration。

注意:枚举接口的功能与迭代器接口相同。此外,Iterator 添加了一个可选的删除操作,并且具有更短的方法名称。新的实现应该考虑使用迭代器而不是枚举。

Java 5 中引入了 ConcurrentMap 接口: -由哈希表支持ConcurrentHashMap的高度并发、高性能的实现。ConcurrentMap此实现在执行检索时从不阻塞,并允许客户端选择更新的并发级别。它旨在替代Hashtable: 除了实现之外ConcurrentMap,它还支持Hashtable.

  • 每个HashMapEntrys 值都是易变的,从而确保竞争修改和后续读取的细粒度一致性;每次读取都反映了最近完成的更新

  • 迭代器和枚举是故障安全的 - 反映自迭代器/枚举创建以来某个时刻的状态;这允许以降低一致性为代价同时读取和修改。它们不会抛出 ConcurrentModificationException。但是,迭代器被设计为一次只能由一个线程使用。

  • 与 相似Hashtable但不同HashMap的是,此类不允许将 null 用作键或值。

public static void main(String[] args) {

    //HashMap<String, Integer> hash = new HashMap<String, Integer>();
    Hashtable<String, Integer> hash = new Hashtable<String, Integer>();
    //ConcurrentHashMap<String, Integer> hash = new ConcurrentHashMap<>();
    
    new Thread() {
        @Override public void run() {
            try {
                for (int i = 10; i < 20; i++) {
                    sleepThread(1);
                    System.out.println("T1 :- Key"+i);
                    hash.put("Key"+i, i);
                }
                System.out.println( System.identityHashCode( hash ) );
            } catch ( Exception e ) {
                e.printStackTrace();
            }
        }
    }.start();
    new Thread() {
        @Override public void run() {
            try {
                sleepThread(5);
                // ConcurrentHashMap  traverse using Iterator, Enumeration is Fail-Safe.
                
                // Hashtable traverse using Enumeration is Fail-Safe, Iterator is Fail-Fast.
                for (Enumeration<String> e = hash.keys(); e.hasMoreElements(); ) {
                    sleepThread(1);
                    System.out.println("T2 : "+ e.nextElement());
                }
                
                // HashMap traverse using Iterator, Enumeration is Fail-Fast.
                /*
                for (Iterator< Entry<String, Integer> > it = hash.entrySet().iterator(); it.hasNext(); ) {
                    sleepThread(1);
                    System.out.println("T2 : "+ it.next());
                    // ConcurrentModificationException at java.util.Hashtable$Enumerator.next
                }
                */
                
                /*
                Set< Entry<String, Integer> > entrySet = hash.entrySet();
                Iterator< Entry<String, Integer> > it = entrySet.iterator();
                Enumeration<Entry<String, Integer>> entryEnumeration = Collections.enumeration( entrySet );
                while( entryEnumeration.hasMoreElements() ) {
                    sleepThread(1);
                    Entry<String, Integer> nextElement = entryEnumeration.nextElement();
                    System.out.println("T2 : "+ nextElement.getKey() +" : "+ nextElement.getValue() );
                    //java.util.ConcurrentModificationException at java.util.HashMap$HashIterator.nextNode
                    //                                          at java.util.HashMap$EntryIterator.next
                    //                                          at java.util.Collections$3.nextElement
                }
                */
            } catch ( Exception e ) {
                e.printStackTrace();
            }
        }
    }.start();
    
    Map<String, String> unmodifiableMap = Collections.unmodifiableMap( map );
    try {
        unmodifiableMap.put("key4", "unmodifiableMap");
    } catch (java.lang.UnsupportedOperationException e) {
        System.err.println("UnsupportedOperationException : "+ e.getMessage() );
    }
}
static void sleepThread( int sec ) {
    try {
        Thread.sleep( 1000 * sec );
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

« 空键和空值

HashMap最多允许一个空键和任意数量的空值。asHashtable甚至不允许单个空键和空值,如果键或值为空,则抛出 NullPointerException。例子

« 同步,线程安全

Hashtable是内部同步的。Hashtable因此,在多线程应用程序中使用是非常安全的。其中 asHashMap不是内部同步的。HashMap因此,在没有外部同步的情况下在多线程应用程序中使用是不安全的。HashMap您可以使用Collections.synchronizedMap()方法进行外部同步。

« 性能

由于Hashtable是内部同步的,这HashtableHashMap.


@看

于 2018-01-04T11:58:44.733 回答
19

对于线程应用程序,您通常可以使用 ConcurrentHashMap - 取决于您的性能要求。

于 2008-09-02T22:38:59.843 回答
18

1.Hashmap并且HashTable都存储键和值。

2.Hashmap可以存储一个密钥为nullHashtable无法存储null

3.HashMap不同步但Hashtable同步。

4.HashMap可以同步Collection.SyncronizedMap(map)

Map hashmap = new HashMap();

Map map = Collections.SyncronizedMap(hashmap);
于 2014-08-27T11:29:41.463 回答
17

除了已经提到的区别之外,需要注意的是,从 Java 8 开始,HashMap将每个桶中使用的 Nodes(链表)动态替换为 TreeNodes(红黑树),这样即使存在高哈希冲突,最坏的情况是搜索

O(log(n)) 对于HashMap Vs O(n) in Hashtable

*上述改进尚未应用于Hashtable, HashMap,LinkedHashMapConcurrentHashMap.

仅供参考,目前,

  • TREEIFY_THRESHOLD = 8:如果一个桶包含超过8个节点,则将链表转换为平衡树。
  • UNTREEIFY_THRESHOLD = 6:当桶变得太小(由于删除或调整大小)时,树将转换回链表。
于 2016-05-04T15:04:15.133 回答
15

HashTable 和 HashMap 有 5 个基本区别。

  1. Maps 允许您迭代和检索键、值以及键值对,而 HashTable 不具备所有这些功能。
  2. 在 Hashtable 中有一个函数 contains(),使用起来非常混乱。因为 contains 的意思略有偏差。是指包含键还是包含值?很难理解。同样,在 Maps 中,我们有 ContainsKey() 和 ContainsValue() 函数,它们非常容易理解。
  3. 在 hashmap 中,您可以在迭代时安全地删除元素。因为在哈希表中是不可能的。
  4. HashTables 默认是同步的,所以它可以很容易地与多个线程一起使用。HashMaps 默认是不同步的,所以只能在单线程中使用。但是您仍然可以使用 Collections util 类的 synchronizedMap(Map m) 函数将 HashMap 转换为同步。
  5. HashTable 不允许空键或空值。HashMap 允许一个空键和多个空值。
于 2013-12-11T12:45:49.900 回答
13

HashMap:它是 java.util 包中的一个类,用于以键值格式存储元素。

Hashtable:它是一个在集合框架中被识别的遗留类。

于 2013-01-31T13:41:05.737 回答
13

我的小贡献:

  1. 和之间的第一个也是最重要的区别是,Hashtable不是线程安全的,而是线程安全的集合。HashMapHashMapHashtable

  2. Hashtable和之间的第二个重要区别HashMap是性能,因为HashMap不同步它的性能优于Hashtable.

  3. Hashtablevs的第三个区别HashMap是它Hashtable是过时的类,你应该在 Java 中使用ConcurrentHashMapHashtable

于 2014-03-18T21:46:56.690 回答
12
  1. Hashtable是同步的,而HashMap不是同步的。
  2. 另一个区别是 in 中的迭代器HashMap是故障安全的,而 enumeratorHashtable则不是。如果您在迭代时更改地图,您就会知道。
  3. HashMap允许其中包含空值,而Hashtable不允许。
于 2013-01-22T05:31:19.947 回答
10

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

于 2013-04-15T14:49:52.357 回答
10

HashMap 和 HashTable

  • 关于 HashMap 和 HashTable 的一些要点。请阅读以下详细信息。

1) Hashtable 和 Hashmap 实现 java.util.Map 接口 2) Hashmap 和 Hashtable 都是基于散列的集合。并致力于散列。所以这些是HashMap和HashTable的相似之处。

  • HashMap 和 HashTable 有什么区别?

1)第一个区别是 HashMap 不是线程安全的,而 HashTable 是 ThreadSafe
2)HashMap 在性能方面更好,因为它不是线程安全的。而 Hashtable 性能并不好,因为它是线程安全的。所以多个线程不能同时访问Hashtable。

于 2014-07-05T06:27:57.807 回答
10

HashMapHashtable都用于以 key 和 value 的形式存储数据。两者都使用散列技术来存储唯一键。但是下面给出的 HashMap 和 Hashtable 类之间存在许多差异。

在此处输入图像描述

于 2019-10-30T11:32:22.790 回答
9

Hashtable:

Hashtable是一种保留键值对值的数据结构。它不允许键和值都为 null。NullPointerException如果您添加空值,您将得到一个。它是同步的。所以它伴随着它的成本。在特定时间只有一个线程可以访问HashTable 。

示例

import java.util.Map;
import java.util.Hashtable;

public class TestClass {

    public static void main(String args[ ]) {
    Map<Integer,String> states= new Hashtable<Integer,String>();
    states.put(1, "INDIA");
    states.put(2, "USA");

    states.put(3, null);    //will throw NullPointerEcxeption at runtime

    System.out.println(states.get(1));
    System.out.println(states.get(2));
//  System.out.println(states.get(3));

    }
}

哈希映射:

HashMap类似于Hashtable,但它也接受键值对。它允许键和值都为 null。它的性能更好就是更好HashTable,因为它是unsynchronized

例子:

import java.util.HashMap;
import java.util.Map;

public class TestClass {

    public static void main(String args[ ]) {
    Map<Integer,String> states = new HashMap<Integer,String>();
    states.put(1, "INDIA");
    states.put(2, "USA");

    states.put(3, null);    // Okay
    states.put(null,"UK");

    System.out.println(states.get(1));
    System.out.println(states.get(2));
    System.out.println(states.get(3));

    }
}
于 2015-02-10T07:44:31.213 回答
6

由于 Java 中的 Hashtable 是 Dictionary 类的子类,由于 Map Interface 的存在,现在已经过时,因此不再使用它。此外,对于实现 Map 接口的类,没有什么是您不能用 Hashtable 做的。

于 2014-03-07T15:02:41.567 回答
6

古老而经典的话题,只想添加这个有用的博客来解释这一点:

http://blog.manishchhabra.com/2012/08/the-5-main-differences-betwen-hashmap-and-hashtable/

Manish Chhabra 的博客

HashMap 和 Hashtable 之间的 5 个主要区别

HashMap 和 Hashtable 都实现了 java.util.Map 接口,但是 Java 开发人员必须了解一些差异才能编写更高效的代码。从 Java 2 平台 v1.2 开始,Hashtable 类被改进为实现 Map 接口,使其成为 Java Collections Framework 的成员。

  1. HashMap 和 Hashtable 之间的主要区别之一是 HashMap 是非同步的,而 Hashtable 是同步的,这意味着 Hashtable 是线程安全的,可以在多个线程之间共享,但 HashMap 不能在没有适当同步的情况下在多个线程之间共享。Java 5 引入了 ConcurrentHashMap,它是 Hashtable 的替代品,提供了比 Java 中的 Hashtable 更好的可扩展性。同步意味着在一个时间点只有一个线程可以修改一个哈希表。基本上,这意味着任何线程在对哈希表执行更新之前都必须获取对象上的锁,而其他线程将等待锁被释放。

  2. HashMap 类大致相当于 Hashtable,除了它允许空值。(HashMap 允许空值作为键和值,而 Hashtable 不允许空值)。

  3. HashMap 与 Hashtable 之间的第三个重要区别是 HashMap 中的 Iterator 是一个快速失败的迭代器,而 Hashtable 的枚举器不是,并且如果任何其他线程通过添加或删除除 Iterator 自己的 remove( ) 方法。但这不是保证行为,JVM 会尽最大努力来完成。这也是 Java 中 Enumeration 和 Iterator 的一个重要区别。

  4. Hashtable 和 HashMap 之间更显着的区别是,由于线程安全和同步,如果在单线程环境中使用,Hashtable 比 HashMap 慢得多。因此,如果您不需要同步并且 HashMap 仅由一个线程使用,它会在 Java 中执行 Hashtable。

  5. HashMap 不保证地图的顺序会随着时间的推移保持不变。

请注意,HashMap 可以通过以下方式同步

Map m = Collections.synchronizedMap(hashMap);

总而言之,Java 中的 Hashtable 和 HashMap 之间存在显着差异,例如线程安全和速度,基于此,如果您绝对需要线程安全,则仅使用 Hashtable,如果您正在运行 Java 5,请考虑在 Java 中使用 ConcurrentHashMap。

于 2014-08-17T09:58:38.813 回答
6

同步或线程安全

Hash Map 不是同步的,因此它不是线程安全的,并且如果没有适当的同步块,它就不能在多个线程之间共享,而 Hashtable 是同步的,因此它是线程安全的。

空键和空值

HashMap 允许一个空键和任意数量的空值。Hashtable 不允许空键或空值。

迭代值

HashMap 中的迭代器是一个快速失败的迭代器,而 Hashtable 的枚举器不是,如果任何其他线程通过添加或删除除 Iterator 自己的 remove() 方法之外的任何元素在结构上修改映射,则抛出 ConcurrentModificationException。

超类和遗产

HashMap 是 AbstractMap 类的子类,而 Hashtable 是 Dictionary 类的子类。

性能

由于 HashMap 不同步,因此它比 Hashtable 更快。

请参阅http://modernpathshala.com/Article/1020/difference-between-hashmap-and-hashtable-in-java以获取与 Java 集合相关的示例和面试问题和测验

于 2016-01-05T18:35:42.627 回答
5

HashMap是模拟的,因此可用于GWT client codeHashtable不是。

于 2013-07-15T09:54:10.873 回答
3

HashMaps 让您可以自由同步,调试更容易

于 2012-08-09T12:28:45.020 回答
3

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

于 2013-07-23T15:50:26.577 回答
0

Hashtable 类是同步的,也就是说,它旨在供处理多线程或多线程进程的应用程序使用。在将应用程序应用于进程的经典情况下,同步类的效率较低,因此 Hashmap 类通常更快。HashTable 类不接受 Null 值,无论是键还是值,而 HashMap 类允许单个键具有 Null 和尽可能多的 null。

于 2017-04-21T15:41:55.313 回答