Java中的HashMap和Hashtable有什么区别?

Java中的#0#1有什么区别?

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

1700636 次浏览

基于信息这里,我建议使用HashMap。我认为最大的优势是Java将防止您在迭代时修改它,除非您通过迭代器进行修改。

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

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

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

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

另请注意,Hashtable扩展了Dictionary类,作为javadocs状态,该类已过时并已被Map接口替换。

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

#0#1在Java上有几个区别:

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

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

  3. HashMap的子类之一是LinkedHashMap,所以如果你想要可预测的迭代顺序(默认情况下是插入顺序),你可以很容易地将HashMap换成LinkedHashMap。如果你使用Hashtable,这就不那么容易了。

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

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

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

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

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

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

Collections.synchronizedMap(myMap);

但要正确实现此逻辑,您需要表单的附加同步

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

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

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

ConcurrentMap.putIfAbsent(key, value);

Hashtable被认为是遗留代码。使用HashMapHashMap的派生可以完成关于Hashtable的任何事情,所以对于新代码,我认为没有任何理由回到Hashtable

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

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

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

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

注意一些重要的术语:

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

HashMap可以通过

Map m = Collections.synchronizeMap(hashMap);

Map提供了Collection视图,而不是通过枚举对象直接支持迭代。Collection视图极大地增强了接口的表现力,如本节后面所述。Map允许您迭代键、值或键-值对;Hashtable不提供第三个选项。Map提供了一种在迭代过程中删除条目的安全方法;Hashtable没有。最后,Map修复了Hashtable接口中的一个小缺陷。Hashtable有一个名为包含的方法,如果Hashtable包含给定值,则返回true。鉴于其名称,如果Hashtable包含给定键,则此方法应返回true,因为键是Hashtable的主要访问机制。Map接口通过重命名方法containsValue消除了这种混淆的根源。此外,这提高了接口的一致性-containsValue平行于containsKey

地图界面

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

例如,比较Java5 Map迭代:

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

与旧的Hashtable方法相比:

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

在Java1.8中,我们还被承诺能够像旧的脚本语言一样构建和访问HashMap:

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

更新时间:不,他们不会降落在1.8…:(

Project Coin的集合增强功能是否会出现在JDK8中?

  • 哈希表是同步的,如果你在单个线程中使用它,你可以使用HashMap,这是一个未同步的版本。未同步的对象通常性能更高一点。顺便说一句,如果多个线程同时访问一个HashMap,并且至少有一个线程在结构上修改了映射,它必须在外部同步。您可以使用:

    将未同步的映射包装成同步的映射
    Map m = Collections.synchronizedMap(new HashMap(...));
  • HashTable can only contain non-null object as a key or as a value. HashMap can contain one null key and null values.

  • The iterators returned by Map are fail-fast, if the map is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove method, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future. Whereas the Enumerations returned by Hashtable's keys and elements methods are not fail-fast.

  • HashTable and HashMap are member of the Java Collections Framework (since Java 2 platform v1.2, HashTable was retrofitted to implement the Map interface).

  • HashTable is considered legacy code, the documentation advise to use ConcurrentHashMap in place of Hashtable if a thread-safe highly-concurrent implementation is desired.

  • HashMap doesn't guarantee the order in which elements are returned. For HashTable I guess it's the same but I'm not entirely sure, I don't find ressource that clearly state that.

HashMap为您提供了同步和调试的自由

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

Java集合矩阵

HashMap将构造一个二次方大小的哈希表,动态增加它,使得你在任何桶中最多有大约八个元素(碰撞),并且对于一般元素类型来说,可以很好地搅拌元素。然而,如果你知道自己在做什么,Hashtable的实现对哈希提供了更好更精细的控制,即你可以使用例如与你的值域大小最接近的素数来修复表大小,这将导致比HashMap更好的性能,即在某些情况下减少碰撞。

除了在这个问题中广泛讨论的明显差异之外,我认为Hashtable是一个“手动驱动”的汽车,您可以更好地控制哈希,而HashMap是“自动驱动”的对应物,通常会表现良好。

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

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

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

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

HashMap被模拟,因此在GWT client code中可用,而Hashtable不是。

HashMap是一个用于将元素存储在key和value中的类format.it不是线程安全的。因为它不同步。因为Hashtable是同步的。Hashmap允许null,但哈斯特布尔不允许null。

HashTable和HashMap有5个基本区别。

  1. 映射允许您迭代和检索键、值以及键-值对,其中HashTable没有所有这些功能。
  2. 哈希表中有一个函数包含(),使用起来非常混乱。因为包含的含义略有偏差。是表示包含键还是包含值?很难理解。地图中也是如此,我们有ContainsKey()和ContainsValue()函数,非常容易理解。
  3. 在hashmap中,您可以在迭代时安全地删除元素。因为它在哈希表中是不可能的。
  4. HashTables默认是同步的,所以它可以很容易地与多个线程一起使用。由于HashMap默认不同步,所以只能与单线程一起使用。但是你仍然可以使用Colltions util类的同步映射(Map m)函数将HashMap转换为同步。
  5. HashTable不允许空键或空值。而HashMap允许一个空键和多个空值。

由于Java中的Hashtable是Dicpedia类的子类,由于Map Interface的存在,它现在已经过时了,因此不再使用。此外,对于实现Map Interface的类,您可以使用Hashtable做任何事情。

我的小小贡献:

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

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

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

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

#30340;如其他人所指出的。

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

输入图片描述

HashMap和HashTable

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

1)Hashtable和Hashmap实现了java.util.Map接口2)Hashmap和Hashtable都是基于哈希的集合。所以这是HashMap和HashTable的相似之处。

  • HashMap和HashTable有什么区别?

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

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

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开发人员必须理解才能编写更高效的代码。从Java2平台v1.2开始,Hashtable类进行了改造以实现Map接口,使其成为Java集合框架

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

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

  3. HashMap与Hashtable之间的第三个重要区别是HashMap中的Iterator是一个快速失败的迭代器,而哈希表的枚举器不是并抛出如果任何其他Thread修改映射,则并发tModificationException在结构上通过添加或删除除Iterator自己之外的任何元素但这不是一个保证的行为,将是由JVM在最佳努力上完成。这也是一个重要的区别在Java中的枚举和迭代器之间。

  4. Hashtable和HashMap之间一个更显着的区别是,由于线程安全和同步,Hashtable要慢得多比HashMap如果在单线程环境中使用。所以如果你不需要同步,HashMap只被一个线程使用,它出来了在Java中执行哈希表。

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

注意,HashMap可以通过

Map m = Collections.synchronizedMap(hashMap);

在总结中,Hashtable和JavaHashMap,例如线程安全和速度,并且仅基于此如果您绝对需要线程安全,如果您正在运行Java5考虑在Java中使用并发HashMap。

HashmapHashTable都存储键和值。

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

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

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

Map hashmap = new HashMap();
Map map = Collections.SyncronizedMap(hashmap);

Hashtable:

哈希表是一个保留键值对值的数据结构。它不允许键和值都为null。如果你添加空值,你会得到一个NullPointerException。它是同步的。所以它有它的成本。在特定时间只有一个线程可以访问哈希表

示例

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,因为它是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);    // Okaystates.put(null,"UK");
System.out.println(states.get(1));System.out.println(states.get(2));System.out.println(states.get(3));
}}

同步或线程安全

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

空键和空值

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

迭代值

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

超类与遗产

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

性能

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

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

除了已经提到的差异之外,应该注意的是,由于Java8,HashMap动态地用TreeNodes(红黑树)替换每个桶中使用的Nodes(链表),因此即使存在高哈希冲突,最坏的情况在搜索

O(log(n))HashMapvs O(n)Hashtable

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

仅供参考,目前,

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

已经有很多很好的答案发表了。我在补充一些新的观点并总结它。

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

HashMap

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

哈希表

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

进一步阅读HashMap和Hashtable在Java上有什么区别?

在此处输入图片描述

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

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

HashMap#1和Hashtable#2都用于表示在<Key, Value>对中表示的一组对象。每个<Key, Value>对称为Entry对象。条目的集合由HashMapHashtable的对象引用。集合中的键必须是唯一的或独特的。[因为它们用于检索映射的值,特定的键。集合中的值可以复制。]


超类、遗留和集合框架成员

Hashtable是JDK1.0中引入的一个遗留类,它是字典类的子类。从JDK1.2开始,Hashtable被重新设计以实现Map接口成为集合框架的成员。HashMap从JDK1.2开始就是Java集合框架的成员。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)。

Hash Map&Hashtable

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

HashMapHashtable在哈希冲突的情况下,他们将映射条目存储在链表中。from Java8 forHashMap如果哈希桶的增长超过某个阈值,该桶将从linked list of entries to a balanced tree切换.这将最坏情况的性能从O(n)提高到O(log n)。当将列表转换为二叉树时,哈希码被用作分支变量。如果在同一个桶中有两个不同的哈希码,一个被认为更大,并且去树的右边,另一个去左边。但是当两个哈希码相等时,HashMap假设键是可比较的,并比较键以确定方向,以便可以维护一些顺序。使HashMap的键具有可比性是一个很好的做法

集合视图迭代,快速故障和故障安全

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

#0本质上是快速失败的。即,如果一个集合在迭代时被修改而不是它自己的删除()方法,它会抛出Con流tModificationException。而#1本质上是故障安全的。如果一个集合在迭代时被修改,它不会抛出任何异常。

根据JavaAPI文档,Iterator始终优先于枚举。

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

Java5引入了并发映射接口ConcurrentHashMap中-由哈希表支持的高度并发、高性能ConcurrentMap实现。此实现在执行检索时从不阻塞,并允许客户端选择更新的并发级别。它旨在作为Hashtable的直接替代品:除了实现ConcurrentMap之外,它还支持Hashtable特有的所有“遗留”方法。

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

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

  • 与#0类似,但与#1不同,此类不允许将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();}}

Null键和Null值

HashMap允许最多一个null键和任意数量的null值。当Hashtable甚至不允许单个null键和null值时,如果键或值为null,则抛出NullPointerException。示例

同步,线程安全

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

性能

由于Hashtable是内部同步的,这使得HashtableHashMap稍慢。


@见

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

在此处输入图片描述