答案 0 :(得分:3519)
Java中HashMap
和Hashtable
之间存在一些差异:
Hashtable
为synchronized,而HashMap
则不是。这使得HashMap
更适合非线程应用程序,因为非同步对象通常比同步对象执行得更好。
Hashtable
不允许null
个键或值。 HashMap
允许一个null
密钥和任意数量的null
值。
HashMap的子类之一是LinkedHashMap
,因此如果您想要可预测的迭代顺序(默认情况下是插入顺序),您可以轻松地换出HashMap
一个LinkedHashMap
。如果您使用Hashtable
,那就不那么容易了。
由于同步对您来说不是问题,我建议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
被视为遗留代码。使用Hashtable
或HashMap
的派生无法完成HashMap
的任何操作,因此对于新代码,我认为没有任何理由可以返回Hashtable
答案 3 :(得分:169)
这个问题经常在面试中被问到,以检查候选人是否理解收集类的正确用法,并了解可用的替代解决方案。
关于一些重要条款的说明
可以通过
同步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。
答案 4 :(得分:121)
HashMap
:使用哈希码索引数组的Map
接口的实现。
Hashtable
:嗨,1998年来了。他们想要回收他们的收藏品。
说真的,你最好完全远离Hashtable
。对于单线程应用程序,您不需要额外的同步开销。对于高度并发的应用程序,偏执同步可能会导致饥饿,死锁或不必要的垃圾收集暂停。就像Tim Howland所指出的那样,你可以改用ConcurrentHashMap
。
答案 5 :(得分:115)
请记住,在引入Java Collections Framework(JCF)之前HashTable
是遗留类,后来为了实现Map
接口而进行了改进。 Vector
和Stack
也是如此。
因此,在新代码中始终远离它们,因为在JCF 中总有更好的替代方法,正如其他人所指出的那样。
以下是您会发现有用的Java collection cheat sheet。请注意,灰色块包含遗留类HashTable,Vector和Stack。
答案 6 :(得分:62)
除了izb所说的,HashMap
允许空值,而Hashtable
则不允许。
另请注意,Hashtable
扩展了Dictionary
类,其Javadocs状态已过时且已被Map
接口替换。
答案 7 :(得分:58)
已经发布了许多好的答案。我添加了一些新的点并总结了它。
HashMap
和Hashtable
都用于以密钥和值格式存储数据。两者都使用散列技术来存储唯一键。
但是下面给出了HashMap和Hashtable类之间的许多区别。
HashMap
HashMap
未同步。它不是线程安全的,并且在没有适当同步代码的情况下不能在许多线程之间共享。 HashMap
允许一个空键和多个空值。 HashMap
是JDK 1.2中引入的新类。 HashMap
很快。 HashMap
同步
Map m = Collections.synchronizedMap(HashMap);
HashMap
。 HashMap
中的迭代器快速失败。 HashMap
继承了AbstractMap类。 <强>哈希表强>
Hashtable
已同步。它是线程安全的,可以与许多线程共享。 Hashtable
不允许任何null键或值。 Hashtable
是遗留类。 Hashtable
很慢。 Hashtable
在内部同步,无法进行同步。 Hashtable
由Enumerator和Iterator遍历。 Hashtable
中的枚举器并非快速失败。 Hashtable
继承了Dictionary类。进一步阅读What is difference between HashMap and Hashtable in Java?
答案 8 :(得分:54)
看看这张图表。它提供了不同数据结构与HashMap和Hashtable之间的比较。比较准确,清晰,易于理解。
答案 9 :(得分:45)
Hashtable
与HashMap
类似,并且具有类似的界面。除非您需要支持旧应用程序或需要同步,否则建议您使用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)
HashMap
和Hashtable
也有很大的算法差异。之前没有人提到这一点,所以这就是我提出这个问题的原因。 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(红黑树)替换每个桶中使用的节点(链表),所以即使是高存在哈希冲突,最糟糕的情况在搜索时是
HashMap
中Hashtable
Vs O(n)的O(log(n))。
*上述改进尚未应用于Hashtable
,但仅适用于HashMap
,LinkedHashMap
和ConcurrentHashMap
。
仅供参考,目前
TREEIFY_THRESHOLD = 8
:如果存储桶包含8个以上的节点,则链表将转换为平衡树。UNTREEIFY_THRESHOLD = 6
:当存储桶变得太小(由于删除或调整大小)时,树会转换回链表。答案 18 :(得分:15)
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);
答案 19 :(得分:13)
HashTable和HashMaps有5个基本区别。
答案 20 :(得分:12)
我的小贡献:
Hashtable
和HashMap
之间的第一个也是最重要的不同之处是,HashMap
不是线程安全的,而Hashtable
是一个线程安全的集合。< / p>
Hashtable
和HashMap
之间的第二个重要区别是效果,因为HashMap
未同步,其效果优于Hashtable
。- 醇>
Hashtable
与HashMap
的第三个区别是Hashtable
是过时的类,您应该在Java中使用ConcurrentHashMap
代替Hashtable
答案 21 :(得分:9)
HashTable是jdk中的遗留类,不应再使用了。用ConcurrentHashMap替换它的用法。如果您不需要线程安全,请使用HashMap而不是threadsafe但更快且使用更少内存。{/ p>
答案 22 :(得分:8)
HashMap和HashTable
1)Hashtable和Hashmap实现了java.util.Map接口 2)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。
HashMap和Hashtable之间的主要区别之一是HashMap是非同步的,而Hashtable是同步的, 表示Hashtable是线程安全的,可以在多个之间共享 线程但HashMap不能在多个线程之间共享 适当的同步。 Java 5引入了ConcurrentHashMap Hashtable的替代方案,提供更好的可伸缩性 Java.Synchronized中的Hashtable意味着只有一个线程可以修改哈希 在一个时间点的表。基本上,它意味着之前的任何线程 对哈希表执行更新必须获取锁定 对象,而其他人将等待释放锁。
HashMap类大致相当于Hashtable,但它允许空值。 (HashMap允许将空值作为键和值而使用 Hashtable不允许空值。)
HashMap与Hashtable之间的第三个显着区别是HashMap中的Iterator是一个失败快速的迭代器,而 Hashtable的枚举器不是和抛出 ConcurrentModificationException如果任何其他Thread修改映射 结构上通过添加或删除除Iterator自己之外的任何元素 remove()方法。但这不是一种保证行为,而且会是 由JVM完成最大努力。这也是一个重要的区别 在Java中的Enumeration和Iterator之间。
Hashtable和HashMap之间的另一个显着区别是,由于线程安全和同步Hashtable要慢得多 如果在单线程环境中使用,则为HashMap。所以,如果你不这样做 需要同步和HashMap只用于一个线程,它出来 在Java中执行Hashtable。
- 醇>
HashMap不保证地图的顺序会随时间保持不变。
请注意,HashMap可以通过
进行同步Map m = Collections.synchronizedMap(hashMap);
总结一下,Hashtable和Hashtable之间存在显着差异 Java中的HashMap,例如线程安全和速度,仅基于此 如果你正在运行,如果你绝对需要线程安全,请使用Hashtable Java 5考虑在Java中使用ConcurrentHashMap。
答案 32 :(得分:2)
答案 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: