HashMap和Hashtable之间的区别?


Answers:


3773

HashMapHashtable在Java中有一些区别:

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

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

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

由于同步对您来说不是问题,因此建议您HashMap。如果同步成为问题,您也可以查看ConcurrentHashMap


84
如果要使HashMap成为线程安全的,请使用Collections.synchronizedMap()
RokStrniša11年

275
我还要评论一下,天真的线程安全Hashtable方法(“同步每种方法都应解决任何并发问题!”)使线程应用程序变得更加糟糕。您最好从外部进行同步HashMap(并考虑后果),或使用ConcurrentMap实现(并利用其扩展的API进行并发)。底线:唯一的原因Hashtable是当旧版API(从1996年开始)需要它时。
erickson 2012年

8
HashMap使程序员可以在实际使用threadSafe代码时灵活地编写它们。我很少需要像ConcurrentHashMap或HashTable这样的线程安全集合。我需要的是同步块中的某些函数集或某些语句是线程安全的。
加拉瓦·阿加瓦尔

2
Hashtable已过时,我们将HashMap用于非线程安全的环境。如果需要线程安全,则可以使用Collections.synchronizedMap()或使用ConcurrentHashMap,它比散列表更有效。
Maneesh Kumar '18

1
它已过时但未弃用,我想知道为什么会这样。我猜想删除此类(和出于相同原因的Vector)会破坏太多现有代码,并使用@Deprecated进行注释将意味着打算删除该代码,但显然不存在。
吉尔·范古普(Jilles van Gurp)'18年

682

请注意,很多答案都说明Hashtable已同步。 在实践中,这几乎买不到您。 同步在访问器/更改器方法上将停止同时从映射中添加或删除两个线程,但是在现实世界中,您经常需要进行额外的同步。

一个非常常见的习惯用法是“先检查后放入”,即在中查找一个条目,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);

53
还要注意,如果修改了HashMap,则指向它的迭代器将变为无效。
克里斯K

3
那么,就线程安全而言,synchronized(myMap){...}与ConcurrentHashMap之间是否有任何区别?
telebog

3
非常正确,我尝试在此处进行解释。.lovehasija.com
2012/

@Bhushan:会尽力而为,这是无法保证的行为:docs.oracle.com/javase/7/docs/api/java/util/HashMap.html
Matt Stephenson

我已经在JVM开发团队中工作了很多年,我可以说Hashtable的内部同步至少对于在客户编写晦涩的并发代码时正确地指责客户的代码至少有用。当原因是并发修改时,我们收到了一些关于HashMap内部失败的投诉(因此“显然”是JDK / JVM错误)。
Hot Licks

363

Hashtable被认为是遗留代码。没有任何事情Hashtable是无法使用HashMap或推导完成的HashMap,因此对于新代码,我看不出回到的任何理由Hashtable


101
从Hashtable javadoc(添加了重点)开始:“从Java 2平台v1.2开始,对该类进行了改进以实现Map接口,使其成为Java Collections Framework的成员。” 但是,您说的很对,它是旧版代码。使用Collections.synchronizedMap(HashMap)可以更有效地获得同步的所有好处。(类似于Vector是Collections.synchronizedList(ArrayList)的旧版本。)
Kip 2010年

15
@ aberrant80:不幸的是,您在两者之间别无选择,并且在为J2ME编程时必须使用Hashtable ...
pwes 2012年

6
该答案应删除。它包含错误的信息,并且有很多支持。
anon58192932

@ anon58192932是否可以编辑问题以解决问题?
GC_

1
我们必须通过标记来引起发帖人@ aberrant80或管理员的注意。举报可能会有所帮助-请立即尝试。
anon58192932 '16

189

面试中经常会问这个问题,以检查应聘者是否理解收集类的正确用法,并了解可用的替代解决方案。

  1. HashMap类是大致相当于Hashtable,除了它是非同步并且允许空值。(HashMap允许将空值用作键和值,而Hashtable不允许使用nulls)。
  2. HashMap 不保证地图的顺序会随着时间的推移保持不变。
  3. HashMap是不同步而已Hashtable同步。
  4. 中的迭代器HashMap是安全的,而如果没有其他线程通过添加或删除除自身 方法之外的任何元素来结构性地修改映射,则为的枚举器为false Hashtable并抛出。但这不是保证的行为,将由JVM尽力而为。ConcurrentModificationExceptionIteratorremove()

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

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

HashMap 可以通过同步

Map m = Collections.synchronizeMap(hashMap);

Map提供了Collection视图,而不是通过Enumeration对象直接支持迭代。集合视图极大地增强了接口的表达能力,如本节后面所述。Map允许您迭代键,值或键值对; Hashtable不提供第三个选项。Map提供了一种在迭代过程中删除条目的安全方法;Hashtable没有。最后,Map修复了Hashtable界面中的一个小缺陷。 Hashtable有一个名为contains的方法,如果Hashtablecontains包含给定值,则返回true 。给定其名称,如果Hashtable包含一个给定的键,则您希望该方法返回true ,因为该键是的主要访问机制Hashtable。Map界面通过重命名方法消除了这种混乱的根源 containsValue。同样,这也提高了接口的一致性 containsValue-parallels containsKey

地图界面


19
该答案至少包含2个重大事实错误。当然,不应该有这么多的批评。
斯蒂芬C

58
1)HashMap的迭代器不是故障安全的。他们是快速失败的。这两个术语在含义上有巨大差异。2)在上没有任何set操作HashMap。3)如果有以前的更改,该put(...)操作将不会抛出IllegalArgumentException。4)如果您更改映射,HashMap 也会发生快速故障行为。5)快速失败行为保证。(HashTable如果您进行并发修改,则不能保证a的行为。实际行为是...不可预测的。)
Stephen C

25
6)Hashtable也不保证地图元素的顺序也会随着时间的推移而保持稳定。(你也许混淆HashtableLinkedHashMap
斯蒂芬ç

4
其他人真的担心这些天的学生会错误地认为,以某种方式获取集合的“同步版本”意味着您不必从外部同步复合操作吗?我最喜欢的一个例子是,thing.set(thing.get() + 1);它经常完全不受保护,而使新手大吃一惊,特别是如果get()and set()方法是同步方法。他们中的许多人都在期待魔术。

HashMap上的迭代器不是安全的
Abdul

130

HashMapMap使用哈希码索引数组的接口的实现。 Hashtable:您好,1998年致电。他们想要他们的收藏API。

严重的是,最好还是远离Hashtable。对于单线程应用程序,您不需要额外的同步开销。对于高度并发的应用程序,偏执同步可能会导致饥饿,死锁或不必要的垃圾收集暂停。就像蒂姆·霍兰德(Tim Howland)指出的那样,您可以ConcurrentHashMap改用它。


这实际上是有道理的。ConcurrentHashMaps使您可以自由地进行同步,调试变得更加容易。
2011年

1
这是特定于Java还是所有哈希映射的实现。

125

请记住,这HashTable是引入Java Collections Framework(JCF)之前的遗留类,后来又进行了改进以实现该Map接口。所以是VectorStack

因此,由于其他人指出的,JCF中总是有更好的替代方法,因此请始终远离新代码

这是Java收集备忘单,您会发现它很有用。请注意,灰色块包含旧类HashTable,Vector和Stack。

在此处输入图片说明


72

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

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

哈希图

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

哈希表

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

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

在此处输入图片说明


在这个答案几乎涵盖(的dupicate) - stackoverflow.com/a/39785829/432903
祈祷

为什么说〜“ 哈希表是旧类 ”?支持文件在哪里。
IgorGanapolsky

2
@IgorGanapolsky你可以看一下这- stackoverflow.com/questions/21086307/...
roottraveller

维护HashMap的成本比TreeMap的成本高。因为HashMap会创建不必要的额外存储桶。
阿卜杜勒

64

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

还要注意Hashtable扩展Dictionary该类,该类作为Javadocs声明是过时的,已由Map接口代替。


3
但这不会使HashTable过时吗?
2011年

自Java 1.7起,@ Pacerier HashTable已过时。
马吉德·阿里·汗

62

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

Java集合矩阵


49

Hashtable与相似,HashMap并且具有相似的界面。建议您使用HashMap,除非需要对旧版应用程序的支持或需要同步,因为Hashtables方法是同步的。因此,就您而言,由于您不是多线程的,HashMaps所以最好的选择是。


36

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

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


36

除了这里已经提到的所有其他重要方面之外,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 ... :(

Project Coin的收藏增强功能是否将在JDK8中使用?


34

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

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


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

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

  • Map返回的迭代器是快速失败的,如果在创建迭代器后的任何时候都对结构进行了结构修改,则除了通过迭代器自己的remove方法之外,该迭代器都将抛出ConcurrentModificationException。因此,面对并发修改,迭代器将迅速而干净地失败,而不是冒着在未来不确定的时间冒任意,不确定的行为的风险。 Hashtable的keys和elements方法返回的枚举并不是快速失败的。

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

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

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


30

HashMap并且Hashtable在算法上也有很大差异。以前没有人提到过这,所以这就是为什么我提起它。HashMap会构造一个具有两个大小幂的哈希表,并动态地增加哈希表,以使您在任何存储桶中最多具有八个元素(冲突),并且对于常规元素类型而言,这些元素将得到很好的搅动。但是,那Hashtable如果您知道自己在做什么实现可以更好地控制散列,即可以使用例如最接近值域大小的素数来固定表大小,这将导致比HashMap更好的性能,即减少冲突在某些情况下。

除了在这个问题中广泛讨论的明显差异之外,我将Hashtable视为“手动驱动”汽车,在其中您可以更好地控制哈希,而将HashMap视为通常可以很好执行的“自动驱动”副本。


27

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


5
它实际上并不能阻止它,它只是检测到它并抛出错误。
Bart van Heukelom

1
我很确定它会在修改基础集合之前抛出ConncurrentModificationException,尽管我可能是错的。
2011年

它将尝试检测并发修改并引发异常。但是,如果您正在对线程做任何事情,那么它就无法做出任何承诺。绝对会发生任何事情,包括破裂
cHao 2011年

24

A- Collection有时称为容器-只是将多个元素分组为一个单元的对象。Collections用于存储,检索,操作和传达聚合数据。集合框架W是用于表示和操作集合的统一体系结构。

HashMap JDK1.2和Hashtable JDK1.0,两者都用来表示一组在表示的对象的<Key, Value>一对。每<Key, Value>对称为Entry对象。参赛作品的收集是由对象简称HashMapHashtable。集合中的键必须唯一或独特。[因为它们用于检索特定键的映射值。集合中的值可以重复。]


« 超类,旧版和收集框架成员

Hashtable是引入的旧类JDK1.0,它是Dictionary类的子类。对JDK1.2Hashtable进行了重新设计,以实现Map接口以使其成为集合框架的成员。HashMap从Java引入框架开始就是Java Collection Framework的成员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 { ... }

« 初始容量和负载系数

容量是哈希表中存储桶的数量,初始容量只是创建哈希表时的容量。请注意,哈希表是打开的:对于“ hashcollision”,单个存储桶存储多个条目,必须按顺序搜索这些条目。负载因子是在自动增加其哈希表容量之前允许哈希表获得的满度的度量。

HashMap使用默认的初始容量(16)和默认的加载因子(0.75)构造一个空哈希表。其中,as 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堆栈后

« 收集视图迭代,快速失败和安全

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

Iterator本质上是快速失败的。也就是说,如果在迭代而不是其自身的remove()方法的同时修改了集合,则抛出ConcurrentModificationException。Enumeration本质上,故障保护在哪里。如果在迭代过程中修改了集合,它不会引发任何异常。

根据Java API文档,迭代器始终优先于枚举。

注意:迭代器接口重复了Enumeration接口的功能。此外,Iterator添加了可选的remove操作,并且具有较短的方法名称。新的实现应考虑优先使用Iterator而不是Enumeration。

Java 5中引入了ConcurrentMap接口ConcurrentHashMap- ConcurrentMap由哈希表支持的高度并发,高性能实现。此实现在执行检索时不会阻塞,并允许客户端选择用于更新的并发级别。它旨在替代Hashtable:除了实现之外ConcurrentMap,它还支持所有特有的“传统”方法Hashtable

  • 每个HashMapEntrys值都是易挥发的,从而确保了精细的一致性,以应对竞争性修改和后续读取;每次读取均反映最近完成的更新

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

  • 类似于HashtableHashMap与之不同,此类不允许将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最多允许一个空键和任意数量的空值。其中as Hashtable甚至不允许单个null键和null值,如果键或值null则抛出NullPointerException。

« 同步,线程安全

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

« 表现

由于Hashtable是内部同步的,因此Hashtable比慢HashMap


@看到


18

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


17

1. HashmapHashTable两个存储键和值。

2. Hashmap可以将一个密钥存储为nullHashtable不能储存null

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

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

Map hashmap = new HashMap();

Map map = Collections.SyncronizedMap(hashmap);

16

除了已经提到的差异,应该指出的是,自从Java 8,HashMap动态替换每个桶使用树节点(红黑树)的节点(链表),这样,即使高哈希冲突存在,最坏的情况下,当搜索

O(log(n))与HashMap Vs O(n)的关系Hashtable

*上述改进还没有被应用到Hashtable还没有,但只HashMapLinkedHashMapConcurrentHashMap

仅供参考,目前,

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

14

HashTable和HashMaps有5个基本区别。

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

13

我的小贡献:

  1. 首先,也是最显著之间的不同HashtableHashMap是,HashMap是不是线程安全的,同时Hashtable是一个线程安全的集合。

  2. Hashtable和之间的第二个重要区别HashMap是性能,由于HashMap未同步,因此其性能优于Hashtable

  3. 关于第三个区别HashtableVS HashMapHashtable已经过时的类,你应该使用ConcurrentHashMap代替HashtableJava编写的。


11

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

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


如果是这样,则不应在注释中作为答案。
manikant gautam

10

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


因为我当时认为其他答案并未消除HashTable,但解释说它是线程安全的。事实是,只要您在代码中看到HashTable,就应该用ConcurrentHashMap替换它,而无需跳动。如果不考虑线程安全性,则可以使用HashMap稍微提高性能。
jontejj

10
  1. Hashtable是同步的,而HashMap不是同步的。
  2. 另一个区别是,中的迭代器HashMap是故障安全的,而中的迭代器Hashtable不是。如果您在迭代时更改地图,就会知道。
  3. HashMap允许其中包含null值,而Hashtable不允许。

3
HashMap迭代器是快速失败而不是安全的。这就是为什么我们有ConcurrentHashMap允许在迭代时进行修改的原因。检查此帖子journaldev.com/122/…–
Pankaj

9

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。


2
否决票,因为此答案在某些方面不正确。Hashtable不实现Map接口,而仅扩展过时的Dictionary类。
Yannis Sermetziadis

8

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

    }
}

5

HashMap是模拟的,因此可以使用,GWT client codeHashtable不能使用。


这是两个api之间差异的全面描述吗?
IgorGanapolsky

是的(原文如此!)。这就是GWT开发人员需要了解的所有信息。
乒乓球

5

古老而经典的话题,只想添加这个有用的博客来说明:

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。


ConcurrentHashMap不是读取同步的,而Hashtable是。因此,如果在写入的同时发生大量读取操作,则如果您关心数据完整性,则哈希表将为您提供更好的服务。
IgorGanapolsky

5

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

在此处输入图片说明


不错的视觉总结!
Nadjib Mami
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.