HashMap和Hashtable的区别?
Java中的HashMap
和Hashtable
有什么区别?
哪个更有效的非线程应用程序?
Java中的HashMap和Hashtable有几个区别:
-
Hashtable
是同步的 ,而HashMap
不是。 这使得HashMap
对于非线程应用程序更好,因为非同步对象通常比同步对象执行得更好。 -
Hashtable
不允许null
键或值。HashMap
允许一个null
键和任意数量的null
值。 -
其中一个HashMap的子类是
LinkedHashMap
,所以如果你想要可预测的迭代顺序(这是默认的插入顺序),你可以很容易地换出一个LinkedHashMap
的HashMap
。 如果你使用Hashtable
这将不那么容易。
由于同步不是你的问题,我build议HashMap
。 如果同步成为问题,你也可以看看ConcurrentHashMap
。
请注意,很多答案指出Hashtable是同步的。 在实践中,这很less买你。 在访问器/增量器方法上的同步将停止两个线程同时添加或从地图中删除,但在现实世界中,你经常需要额外的同步。
一个非常常见的习惯用法是“检查然后放置” – 即在地图中查找一个条目,如果它尚不存在,则添加它。 无论使用Hashtable还是HashMap,这都不是primefaces操作。
等价的同步HashMap可以通过以下方式获得:
Collections.synchronizedMap(myMap);
但是为了正确地实现这个逻辑,你需要额外的表单同步 :
synchronized(myMap) { if (!myMap.containsKey("tomato")) myMap.put("tomato", "red"); }
即使遍历Hashtable的条目(或由Collections.synchronizedMap获取的HashMap)也不是线程安全的,除非您还通过附加同步来防止修改Map。
ConcurrentMap接口(例如ConcurrentHashMap )的实现通过包含线程安全的check-then-act语义来解决这个问题,例如:
ConcurrentMap.putIfAbsent(key, value);
没有人提到这个事实,即 而且, Hashtable
不是 Java集合框架的一部分 – 它只是提供了一个类似的API。Hashtable
被认为是遗留代码。 没有什么能够使用HashMap
或HashMap
派生无法完成的Hashtable
,所以对于新的代码,我没有看到任何回到Hashtable
理由。
这个问题经常在面试中被问到是否候选人理解收集类的正确使用,并知道可用的替代解决scheme。
- HashMap类大致等同于Hashtable,不同之处在于它不是同步的并且允许空值。 (HashMap允许空值作为键和值,而Hashtable不允许空值)。
- HashMap不能保证地图的顺序会随着时间的推移保持不变。
- HashMap是非同步的,而Hashtable是同步的。
- HashMap中的迭代器是安全的,而Hashtable的枚举器不是,并且如果其他任何线程通过添加或除去Iterator自身的remove()方法之外的任何元素来修改映射,则抛出ConcurrentModificationException。 但是,这不是一个有保证的行为,并将尽最大努力由JVM完成。
关于一些重要条款的说明
- 同步意味着只有一个线程可以在一个时间点修改一个哈希表。 基本上,这意味着在执行哈希表更新之前,任何线程都必须获取对象上的锁,而其他人将等待锁释放。
- Fail-safe与迭代器的上下文相关。 如果在集合对象上创build了一个迭代器,并且某个其他线程尝试从“结构上”修改集合对象,则会引发并发修改exception。 其他线程可能调用“set”方法,因为它不会“结构性”地修改集合。 但是,如果在调用“set”之前,集合已经在结构上进行了修改,则会抛出“IllegalArgumentException”exception。
- 结构修改意味着删除或插入可有效改变地图结构的元素。
HashMap可以被同步
Map m = Collections.synchronizeMap(hashMap);
Map提供Collection视图,而不是直接支持通过Enumeration对象进行迭代。 集合视图大大提高了界面的performance力,这在本节后面讨论。 Map允许迭代键,值或键值对; 散列表不提供第三个选项。 Map提供了一个安全的方法来删除迭代中的条目; 哈希表没有。 最后,Map修复了Hashtable接口中的一个小缺陷。 Hashtable有一个叫做contains的方法,如果Hashtable包含给定的值,则返回true。 考虑到它的名字,如果Hashtable包含一个给定的键,那么你会希望这个方法返回true,因为这个键是Hashtable的主要访问机制。 Map接口通过重命名方法containsValue消除了这个混淆的来源。 此外,这提高了界面的一致性 – containsValue类似containsKey。
地图界面
请记住,在引入Java集合框架(JCF)之前, HashTable
是遗留类,后来被改进以实现Map
接口。 Vector
和Stack
。
因此,在其他代码中总会有更好的select,因此在新的代码中总是远离它们 。
这里是你会发现有用的Java集合备忘单 。 注意灰色块包含遗留类HashTable,Vector和Stack。
HashMap
:使用散列码来索引数组的Map
接口的实现。 Hashtable
:你好,1998年。 他们希望他们的收集API回来。
但是严重的是,你最好不要使用Hashtable
。 对于单线程应用程序,您不需要额外的同步处理开销。 对于高度并发的应用程序,偏执同步可能会导致饥饿,死锁或不必要的垃圾收集暂停。 像Tim Howland指出的那样,你可以使用ConcurrentHashMap
来代替。
除了什么izb说, HashMap
允许空值,而Hashtable
不。
另请注意, Hashtable
扩展了Dictionary
类,它作为Javadocs状态已经过时,并被Map
接口所取代。
看看这个图表。 它提供了不同的数据结构与HashMap和Hashtable之间的比较。 比较是精确的,清晰的,易于理解的。
Java集合matrix
Hashtable
与HashMap
类似,具有类似的接口。 除非需要对传统应用程序的支持,否则build议使用HashMap
,否则需要同步,因为Hashtables
方法是同步的。 所以在你的情况,因为你不是multithreading, HashMaps
是你最好的select。
散列表和散列表之间的另一个主要区别是,HashMap中的Iterator是快速失败的,而Hashtable的枚举符则不是,并且如果任何其他线程通过添加或删除除Iterator自身的remove()方法之外的任何元素来修改映射,则抛出ConcurrentModificationException。 但是,这不是一个有保证的行为,而是由JVM尽最大努力完成的。“
我的来源: http : //javarevisited.blogspot.com/2010/10/difference-between-hashmap-and.html
除了这里已经提到的所有其他重要方面之外,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中,我们也承诺能够像旧的脚本语言一样构build和访问HashMap:
Map<String,Integer> map = { "orange" : 12, "apples" : 15 }; map["apples"];
更新:不,他们不会在1.8 …
Project Coin的集合增强function将在JDK8中进行吗?
-
HashTable是同步的,如果你在一个线程中使用它,你可以使用HashMap ,它是一个非同步的版本。 不同步的对象往往更高效一些。 顺便说一下,如果多个线程同时访问HashMap,并且至less有一个线程在结构上修改了映射,则它必须在外部同步。 Youn可以使用下面的代码封装一个同步的地图:
Map m = Collections.synchronizedMap(new HashMap(...));
-
HashTable只能包含非null对象作为键或值。 HashMap可以包含一个空键和空值。
-
由Map返回的迭代器是快速失败的,如果迭代器创build后随时都可以在结构上修改映射,除了通过迭代器自己的remove方法以外,迭代器将抛出
ConcurrentModificationException
。 因此,在并发修改的情况下,迭代器快速而干净地失败,而不是在未来的未定的时间冒着任意的,不确定的行为冒险。 而 Hashtable的键和元素方法返回的枚举不是快速失败的。 -
HashTable和HashMap是Java Collections Framework的成员(自Java 2平台v1.2以来,HashTable被改进以实现Map接口)。
-
HashTable被认为是遗留代码,如果需要线程安全高度并行的实现,文档build议使用ConcurrentHashMap代替Hashtable。
-
HashMap不保证元素返回的顺序。 对于HashTable我猜这是一样的,但我不完全确定,我没有find明确说明的资源。
HashMap
和Hashtable
也有显着的algorithm差异。 之前没有人提到过这个,所以我才把它提出来。 HashMap
将构造一个具有两个尺寸幂的散列表,dynamic增加它,使得在任何存储桶中至多有八个元素(冲突),并且对于一般元素types将非常好地搅动元素。 然而,如果你知道你在做什么, Hashtable
实现提供了更好更好的哈希控制,也就是说,你可以使用例如最接近你的值域大小的素数来修复表的大小,这将导致比HashMap更好的性能,即更less一些情况下的碰撞。
除了在这个问题上广泛讨论的显而易见的区别之外,我将Hashtable看作是一个“手动驱动”的汽车,您可以更好地控制散列和HashMap作为一般性能良好的“自动驾驶”对象。
哈希表是同步的,而哈希表不是。 这使得Hashtable比Hashmap慢。
对于非线程应用程序,使用HashMap,因为它们在function上是相同的。
Java中HashMap和Hashtable的区别:
1)线程安全
- HashTable是内部同步的。
- 因此,在multithreading应用程序中使用HashTable是非常安全的。
- HashMap不在内部同步的地方。
- 因此,在没有外部同步的情况下,在multithreading应用程序中使用HashMap是不安全的。
- 您可以使用Collections.synchronizedMap()方法从外部同步HashMap。
2)inheritance自
- 虽然HashMap和HashTable都实现了Map接口,但它们扩展了两个不同的类。
- HashMap扩展了AbstractMap类,其中HashTableinheritance了java中遗留类的Dictionary类。
3)空键和空值
- HashMap允许最多一个空键和任意数量的空值。
- HashTable甚至不允许单个空键和空值。
4)遍历
- HashMap只返回用于遍历HashMap元素的迭代器。
- HashTable返回Iterator以及Enumeration,它可以用来遍历HashTable的元素。
5)失效 – 快速与失效 – 安全
- 由HashMap返回的迭代器本质上是快速失败的,即如果在迭代器自身的remove()方法以外的Iterator创build之后修改了HashMap,则抛出ConcurrentModificationExceptionexception。
- 另一方面,由HashTable返回的Enumeration本质上是自动防故障的,即如果在创buildEnumeration之后修改了HashTable,它们不会抛出任何exception。
6)性能
- 由于HashTable是内部同步的,这使得HashTable比HashMap稍慢。
7)遗产类
- HashTable是一个遗留类。
- 几乎认为这是贬值的原因。
- 从JDK 1.5开始,ConcurrentHashMap被认为是比HashTable更好的select。
8)Java Collection框架的成员
- HashMap是在JDK 1.2中引入之初的Java Collection Framework的成员。
- 但是,HashTable在JDK 1.2之前。 从JDK 1.2开始,实现了Map接口,使之成为集合框架的一员。
哪个更有效的非线程应用程序?
-
哈希表是同步的,而哈希表不是。
-
这使得HashMap对于非线程应用程序更好,因为非同步对象通常比同步对象执行得更好。
根据这里的信息,我build议使用HashMap。 我认为最大的好处是Java会阻止你在迭代它时修改它,除非你通过迭代器来完成。
对于线程应用程序,您通常可以使用ConcurrentHashMap – 取决于您的性能要求。
HashMap和HashTable / HashMap vs HashTable之间的区别
-
同步或线程安全:这是两者之间最重要的区别。 HashMap是非同步的,不是线程安全的。另一方面,HashTable是线程安全和同步的。 何时使用HashMap? 答案是如果您的应用程序不需要任何multithreading任务,换句话说hashmap对于非线程应用程序更好。 应该在multithreading应用程序中使用HashTable。
-
空键和空值:Hashmap允许一个空键和任意数量的空值,而Hashtable不允许HashTable对象中的空键和空值。
-
迭代值:使用迭代器迭代Hashmap对象值.HashTable是除了使用枚举器遍历HashTable对象值的向量之外唯一的类。
-
失败快速迭代器:Hashmap中的迭代器是快速迭代器,而Hashtable的枚举器则不是。 根据Oracle Docs,如果在迭代器以任何方式创build之后(除了迭代器自己的remove方法),在任何时候结构修改Hashtable,那么迭代器将抛出ConcurrentModificationException。 结构修改意味着从Collection对象(这里是散列表或散列表)添加或删除元素。 因此,Hashtable键和元素方法返回的枚举不会失败快。我们已经解释了迭代器和枚举之间的区别。
-
性能:HashMap比前者更加快速并且使用的内存less于Hashtable。 与单线程环境中的Hashtable等同步对象相比,非同步对象的性能通常要好得多。
-
超类和传统:Hashtable是Dictionary类的一个子类,现在已经在Jdk 1.7中被淘汰了,所以它不再被使用了。 最好是外部同步HashMap或使用ConcurrentMap实现(例如ConcurrentHashMap).HashMap是AbstractMap类的子类。 尽pipeHashtable和HashMap具有不同的超类,但它们都是“Map”抽象数据types的实现。
已经发布了很多很好的答案。 我添加了几个新点并对其进行总结。
HashMap
和Hashtable
都用于以键和值forms存储数据 。 两者都使用哈希技术来存储唯一的密钥。 但是下面给出了HashMap和Hashtable类之间的区别。
HashMap中
1) HashMap
是不同步的。 它不是线程安全的,不能在许multithreading之间共享,没有适当的同步代码。
2) HashMap
允许一个空键和多个空值。
3) HashMap
是JDK 1.2中引入的一个新类。
4) HashMap
速度很快。
5)通过调用这个代码,我们可以使HashMap
同步
Map m = Collections.synchronizedMap(HashMap);
6) HashMap
被Iterator遍历。
7) HashMap
迭代器是快速失败的。
8) HashMap
inheritanceAbstractMap类。
哈希表
1) Hashtable
是同步的。 它是线程安全的,可以与许multithreading共享。
2) Hashtable
不允许任何空键或值。
3) Hashtable
是一个传统的类。
4) Hashtable
很慢。
5) Hashtable
是内部同步的,不能不同步。
6) Hashtable
由Enumerator和Iterator遍历。
7) Hashtable
枚举器不是快速失败的。
8) Hashtable
inheritanceDictionary类。
更多阅读Java中的HashMap和Hashtable有什么区别?
除了已经提到的差异之外,应该注意的是,从Java 8开始, HashMap
dynamic地用TreeNodes(红黑树)replace每个桶中使用的节点(链表),所以即使存在高散列冲突,最坏的情况当search是
O(log(n))用于Hashtable
HashMap
Vs O(n)。
*上述改进尚未应用于Hashtable
,但仅适用于HashMap
, LinkedHashMap
和ConcurrentHashMap
。
仅供参考,目前,
-
TREEIFY_THRESHOLD = 8
:如果一个桶包含8个以上的节点,链表将被转换成平衡树。 -
UNTREEIFY_THRESHOLD = 6
:当一个桶变得太小(由于移除或resize)树被转换回链接列表。
与HashTable和HashMaps有5个基本的区别。
- 地图允许您迭代和检索键,值和键值对,其中HashTable不具备所有这些function。
- 在Hashtable中有一个函数contains(),这是非常容易使用的。 因为含义的含义稍有偏差。 是否意味着包含密钥或包含值? 很难理解。 在Maps中我们有ContainsKey()和ContainsValue()函数,这很容易理解。
- 在hashmap中,可以安全地迭代时删除元素。 因为它不可能在哈希表中。
- HashTables默认是同步的,所以它可以很容易地用于多个线程。 HashMap在默认情况下不是同步的,因此只能用于单线程。 但是仍然可以使用Collections util类的synchronizedMap(Map m)函数将HashMap转换为同步。
- HashTable将不允许空键或空值。 HashMap允许一个空键和多个空值。
1. Hashmap
和HashTable
都存储键和值。
2. Hashmap
可以存储一个键为null
。 Hashtable
不能存储null
。
3. HashMap
不同步,但Hashtable
是同步的。
4. HashMap
可以与Collection.SyncronizedMap(map)
同步
Map hashmap = new HashMap(); Map map = Collections.SyncronizedMap(hashmap);
我的小小贡献:
Hashtable
和HashMap
之间的第一个和最显着的不同之处在于,HashMap
不是线程安全的,而Hashtable
是一个线程安全的集合。
Hashtable
和HashMap
之间的第二个重要区别是性能,因为HashMap
不同步,它比Hashtable
更好。
Hashtable
与HashMap
第三个区别是Hashtable
是过时的类,您应该使用ConcurrentHashMap
来代替Java中的Hashtable
。
HashTable是jdk中不应该使用的遗留类。 用ConcurrentHashMapreplace它的用法。 如果您不需要线程安全性,请使用HashMap ,它不是线程安全的,但速度更快,占用的内存也更less。
1)哈希表是同步的,而哈希表不是。 2)另一个区别是HashMap中的迭代器是安全的,而Hashtable的枚举器则不是。 如果在迭代过程中更改地图,则会知道。
3)HashMap允许空值,而Hashtable不允许。
HashMap: – 它是java.util包中的一个类,用于存储key和value格式的元素。
哈希表:这是一个正在被收集框架认可的遗留类
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。
HashMaps给你自由的同步和debugging更容易
HashMap
是模拟的,因此可用于GWT client code
而Hashtable
则不是。
HashMap是一个用于存储键和值格式的元素的类,它不是线程安全的。 因为它不同步,因为Hashtable是synchronized.Hashmap允许为null,但hastable不允许为null。