HashMap和Hashtable之间的区别?

时间:2008-09-02 20:12:00

标签: java collections hashmap hashtable

Java中HashMapHashtable之间有什么区别?

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

36 个答案:

答案 0 :(得分:3519)

Java中HashMapHashtable之间存在一些差异:

  1. Hashtablesynchronized,而HashMap则不是。这使得HashMap更适合非线程应用程序,因为非同步对象通常比同步对象执行得更好。

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

  3. HashMap的子类之一是LinkedHashMap,因此如果您想要可预测的迭代顺序(默认情况下是插入顺序),您可以轻松地换出HashMap一个LinkedHashMap。如果您使用Hashtable,那就不那么容易了。

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

答案 1 :(得分:631)

请注意,很多答案都说明Hashtable是同步的。 在实践中,这很少购买。同步在accessor / mutator上的方法将停止两个线程同时添加或从地图中删除,但在现实世界中,您经常需要额外的同步。

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

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

Collections.synchronizedMap(myMap);

但要正确实现此逻辑,您需要格式的其他同步

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

即使迭代Hashtable的条目(或HashMap获得的Collections.synchronizedMap)也不是线程安全的,除非你还保护Map不被修改同步。

ConcurrentMap接口的实现(例如ConcurrentHashMap)通过包含线程安全检查然后行为语义来解决其中的一些问题,例如:

ConcurrentMap.putIfAbsent(key, value);

答案 2 :(得分:326)

Hashtable被视为遗留代码。使用HashtableHashMap的派生无法完成HashMap的任何操作,因此对于新代码,我认为没有任何理由可以返回Hashtable

答案 3 :(得分:169)

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

  1. HashMap类大致相当于Hashtable,除了它是非同步的并且允许空值。 (HashMap允许空值作为键和值,而Hashtable不允许空值)。
  2. HashMap不保证地图的顺序会随着时间的推移保持不变。
  3. HashMap是非同步的,而Hashtable是同步的。
  4. HashMap中的迭代器是故障安全的,而Hashtable的枚举器不是,如果任何其他Thread通过添加或删除除Iterator自己的remove()方法之外的任何元素来修改地图,则抛出ConcurrentModificationException。但这不是一种保证行为,将由JVM尽最大努力完成。
  5. 关于一些重要条款的说明

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

      同步HashMap

      Map m = Collections.synchronizeMap(hashMap);

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

        

      The Map Interface

答案 4 :(得分:121)

HashMap:使用哈希码索引数组的Map接口的实现。 Hashtable:嗨,1998年来了。他们想要回收他们的收藏品。

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

答案 5 :(得分:115)

请记住,在引入Java Collections Framework(JCF)之前HashTable是遗留类,后来为了实现Map接口而进行了改进。 VectorStack也是如此。

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

以下是您会发现有用的Java collection cheat sheet。请注意,灰色块包含遗留类HashTable,Vector和Stack。

enter image description here

答案 6 :(得分:62)

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

另请注意,Hashtable扩展了Dictionary类,其Javadocs状态已过时且已被Map接口替换。

答案 7 :(得分:58)

已经发布了许多好的答案。我添加了一些新的点并总结了它。

HashMapHashtable都用于以密钥和值格式存储数据。两者都使用散列技术来存储唯一键。 但是下面给出了HashMap和Hashtable类之间的许多区别。

HashMap

  1. HashMap未同步。它不是线程安全的,并且在没有适当同步代码的情况下不能在许多线程之间共享。
  2. HashMap允许一个空键和多个空值。
  3. HashMap是JDK 1.2中引入的新类。
  4. HashMap很快。
  5. 我们可以通过调用此代码使HashMap同步      Map m = Collections.synchronizedMap(HashMap);
  6. Iterator遍历了
  7. HashMap
  8. HashMap中的迭代器快速失败。
  9. HashMap继承了AbstractMap类。
  10. <强>哈希表

    1. Hashtable已同步。它是线程安全的,可以与许多线程共享。
    2. Hashtable不允许任何null键或值。
    3. Hashtable是遗留类。
    4. Hashtable很慢。
    5. Hashtable在内部同步,无法进行同步。
    6. Hashtable由Enumerator和Iterator遍历。
    7. Hashtable中的枚举器并非快速失败。
    8. Hashtable继承了Dictionary类。
    9. 进一步阅读What is difference between HashMap and Hashtable in Java?

      enter image description here

答案 8 :(得分:54)

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

Java Collection Matrix

答案 9 :(得分:45)

HashtableHashMap类似,并且具有类似的界面。除非您需要支持旧应用程序或需要同步,否则建议您使用HashMap,因为Hashtables方法已同步。因此,在您不是多线程的情况下,HashMaps是您最好的选择。

答案 10 :(得分:34)

散列表和散列映射之间的另一个关键区别是HashMap中的Iterator是快速失​​败的,而Hashtable的枚举器不是,如果任何其他Thread通过添加或删除除Iterator自己的remove之外的任何元素来修改映射,则抛出ConcurrentModificationException( ) 方法。但这不是一种保证行为,将由JVM尽最大努力完成。“

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

答案 11 :(得分:33)

除了这里已经提到的所有其他重要方面之外,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中,我们也承诺能够构建和访问HashMaps,就像使用优秀的旧脚本语言一样:

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

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

Are Project Coin's collection enhancements going to be in JDK8?

答案 12 :(得分:28)

  • HashTable已同步,如果您在单个线程中使用它,则可以使用HashMap,这是一个不同步的版本。非同步对象通常更具性能。顺便说一下,如果多个线程同时访问HashMap,并且至少有一个线程在结构上修改了映射,则必须在外部进行同步。 您可以使用以下方法将未同步的地图包装在同步的地图中:

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

  • Map返回的迭代器是快速失败的,如果在创建迭代器后的任何时候对映射进行结构修改,除了通过迭代器自己的remove方法之外,迭代器将抛出{{1 }}。因此,在并发修改的情况下,迭代器快速而干净地失败,而不是在未来的未确定时间冒着任意的,非确定性行为的风险。 然而 Hashtable的键和元素方法返回的枚举不是快速失败的。

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

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

  • HashMap不保证返回元素的顺序。对于HashTable,我猜它是一样的,但我不完全确定,我找不到明确说明的资源。

答案 13 :(得分:27)

HashMapHashtable也有很大的算法差异。之前没有人提到这一点,所以这就是我提出这个问题的原因。 HashMap将构造一个具有两个大小幂的哈希表,动态地增加它,这样你在任何桶中最多只有八个元素(冲突),并且会很好地激发一般元素类型的元素。但是,如果您知道自己在做什么,Hashtable实现可以更好,更精细地控制散列,即您可以使用例如与您的值域大小最接近的素数,这将导致比HashMap更好的性能,即在某些情况下更少的冲突。

除了在这个问题中广泛讨论的显而易见的差异之外,我认为Hashtable是一个“手动驱动”汽车,你可以更好地控制散列和HashMap作为通常表现良好的“自动驱动”对应物。 / p>

答案 14 :(得分:25)

Hashtable是同步的,而HashMap则不是。这使得Hashtable比Hashmap慢。

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

答案 15 :(得分:23)

根据信息here,我建议使用HashMap。我认为最大的优点是Java会阻止你在迭代它时修改它,除非你通过迭代器完成它。

答案 16 :(得分:17)

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

答案 17 :(得分:15)

除了已经提到的差异之外,应该注意的是,自Java 8起,HashMap动态地用TreeNodes(红黑树)替换每个桶中使用的节点(链表),所以即使是高存在哈希冲突,最糟糕的情况在搜索时

{p> HashMapHashtable Vs O(n)的O(log(n))。

*上述改进尚未应用于Hashtable,但仅适用于HashMapLinkedHashMapConcurrentHashMap

仅供参考,目前

  • TREEIFY_THRESHOLD = 8:如果存储桶包含8个以上的节点,则链表将转换为平衡树。
  • UNTREEIFY_THRESHOLD = 6:当存储桶变得太小(由于删除或调整大小)时,树会转换回链表。

答案 18 :(得分:15)

1. HashmapHashTable都存储键和值。

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

3. HashMap未同步但Hashtable已同步。

4. HashMap可以与Collection.SyncronizedMap(map)

同步
Map hashmap = new HashMap();

Map map = Collections.SyncronizedMap(hashmap);

答案 19 :(得分:13)

HashTable和HashMaps有5个基本区别。

  1. Maps允许您迭代和检索键,值和两个键值对,其中HashTable不具备所有这些功能。
  2. 在Hashtable中有一个函数contains(),使用起来非常混乱。因为contains的含义略有偏差。它意味着包含密钥还是包含值?难以理解。在Maps中我们有ContainsKey()和ContainsValue()函数,它们很容易理解。
  3. 在hashmap中,您可以安全地在迭代时删除元素。在哈希表中不可能的地方。
  4. HashTables默认是同步的,因此可以轻松地与多个线程一起使用。默认情况下,HashMaps不同步,因此只能与单个线程一起使用。但您仍然可以使用Collections util类的synchronizedMap(Map m)函数将HashMap转换为同步。
  5. HashTable不允许使用null键或null值。 HashMap允许一个空键和多个空值的地方。

答案 20 :(得分:12)

我的小贡献:

  
      
  1. HashtableHashMap之间的第一个也是最重要的不同之处是,HashMap不是线程安全的,而Hashtable是一个线程安全的集合。< / p>

  2.   
  3. HashtableHashMap之间的第二个重要区别是效果,因为HashMap未同步,其效果优于Hashtable

  4.   
  5. HashtableHashMap的第三个区别是Hashtable是过时的类,您应该在Java中使用ConcurrentHashMap代替Hashtable

  6.   

答案 21 :(得分:9)

HashTable是jdk中的遗留类,不应再使用了。用ConcurrentHashMap替换它的用法。如果您不需要线程安全,请使用HashMap而不是threadsafe但更快且使用更少内存。{/ p>

答案 22 :(得分:8)

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。

答案 23 :(得分:8)

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

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

答案 24 :(得分:8)

1)Hashtable是同步的,而hashmap不是。 2)另一个区别是HashMap中的迭代器是故障安全的,而Hashtable的枚举器则不是。如果你在迭代时更改地图,你就会知道。

3)HashMap允许空值,而Hashtable则不允许。

答案 25 :(得分:7)

<强> 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中:

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));

    }
}

答案 26 :(得分:4)

HashMap已模拟,因此可在GWT client code中使用,而Hashtable则不可用。

答案 27 :(得分:4)

同步或线程安全

哈希映射不是同步的,因此它不是安全的,如果没有正确的同步块,它不能在多个线程之间共享,而Hashtable是同步的,因此它是线程安全的。

空键和空值

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

迭代值

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

超级和遗产

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

效果

由于HashMap未同步,因此与Hashtable相比速度更快。

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

答案 28 :(得分:4)

HashMaps为您提供了同步自由,调试更加轻松

答案 29 :(得分:3)

HashMap是一个用于以key和value格式存储元素的类。它不是线程安全的。 因为Hashtable是synchronized.Hashmap允许null但hastable不允许null。

答案 30 :(得分:2)

由于Java中的Hashtable是Dictionary类的子类,由于Map接口的存在而现在已经过时,因此不再使用它。此外,对于实现可以使用Hashtable执行Map接口的类,您无法做任何事情。

答案 31 :(得分:2)

旧的和经典的主题,只想添加这个有用的博客来解释这个:

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.Synchronized中的Hashtable意味着只有一个线程可以修改哈希   在一个时间点的表。基本上,它意味着之前的任何线程   对哈希表执行更新必须获取锁定   对象,而其他人将等待释放锁。

  2.   
  3. HashMap类大致相当于Hashtable,但它允许空值。 (HashMap允许将空值作为键和值而使用   Hashtable不允许空值。)

  4.   
  5. HashMap与Hashtable之间的第三个显着区别是HashMap中的Iterator是一个失败快速的迭代器,而   Hashtable的枚举器不是和抛出   ConcurrentModificationException如果任何其他Thread修改映射   结构上通过添加或删除除Iterator自己之外的任何元素   remove()方法。但这不是一种保证行为,而且会是   由JVM完成最大努力。这也是一个重要的区别   在Java中的Enumeration和Iterator之间。

  6.   
  7. Hashtable和HashMap之间的另一个显着区别是,由于线程安全和同步Hashtable要慢得多   如果在单线程环境中使用,则为HashMap。所以,如果你不这样做   需要同步和HashMap只用于一个线程,它出来   在Java中执行Hashtable。

  8.   
  9. HashMap不保证地图的顺序会随时间保持不变。

  10.         

    请注意,HashMap可以通过

    进行同步
    Map m = Collections.synchronizedMap(hashMap);
    
         

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

答案 32 :(得分:2)

HashMap Hashtable 均用于存储键和值形式的数据。两者都使用哈希技术来存储唯一密钥。 但下面给出的HashMap和Hashtable类之间有很多区别。

enter image description here

答案 33 :(得分:0)

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

答案 34 :(得分:0)

Hashtable 是线程安全的,可以在应用程序中的多个线程之间共享。

另一方面,HashMap 是不同步的,如果没有额外的同步代码,就不能被多个线程访问。我们可以使用 Collections.synchronizedMap() 来制作 HashMap 的线程安全版本。我们也可以直接创建自定义锁代码或使用 synchronized 关键字使代码成为线程安全的。

HashMap 不是同步的,因此它比 Hashtable 更快并且使用更少的内存。通常,在单线程应用程序中,未同步的对象比同步的对象要快。

Hashtable 根本不允许为 null。

对于非同步或单线程应用程序,我们应该使用 HashMap。

自 JDK 1.8 起,Hashtable 已被弃用。然而,ConcurrentHashMap 是一个很好的 Hashtable 替代品。我们应该考虑在多线程应用中使用 ConcurrentHashMap。

答案 35 :(得分:0)

HashMap 和 Hashtable 将键/值对存储在哈希表中。使用 Hashtable 或 HashMap 时,我们指定一个用作键的对象以及要链接到该键的值。然后对键进行散列,所得散列代码用作将值存储在表中的索引。 示例 Java 代码。

// A sample Java program to demonstrate HashMap and HashTable
import java.util.*;
import java.lang.*;
import java.io.*;
 
// Name of the class has to be "Main" only if the class is public
class Ideone
{
    public static void main(String args[])
    {
        // hashtable
        Hashtable<Integer,String> ht=new Hashtable<Integer,String>();
        ht.put(101," test");
        ht.put(101,"test1");
        ht.put(102,"test2");
        ht.put(103,"test3");
        System.out.println("-------------Hash table--------------");
        for (Map.Entry m:ht.entrySet()) {
            System.out.println(m.getKey()+" "+m.getValue());
        }
 
        // hashmap
        HashMap<Integer,String> hm=new HashMap<Integer,String>();
        hm.put(100,"test");
        hm.put(104,"test1"); 
        hm.put(101,"test2");
        hm.put(102,"test3");
        System.out.println("-----------Hash map-----------");
        for (Map.Entry m:hm.entrySet()) {
            System.out.println(m.getKey()+" "+m.getValue());
        }
    }
}

---- Hash table --- 103 test3 102 test2 101 test1
---- Hash map   --- 100 test 101 test2 102 test3 104 test1

Hashmap 与 Hashtable

  1. HashMap 是非同步的。它不是线程安全的,如果没有适当的同步代码,就不能在许多线程之间共享,而 Hashtable 是同步的。它是线程安全的,可以与多个线程共享。
  2. HashMap 允许一个空键和多个空值,而 Hashtable 不允许任何空键或值。
  3. 如果不需要线程同步,HashMap 通常优于 HashTable 为什么 HashTable 不允许 null 而 HashMap 呢? 要成功地从 HashTable 存储和检索对象,用作键的对象必须实现 hashCode 方法和 equals 方法。由于 null 不是对象,因此无法实现这些方法。 HashMap 是对 Hashtable 的高级版本和改进。 HashMap 是后来创建的。