章
目
录
在入门级Java程序员的面试中,你可能会遇到Hashtable与HashMap的问题。虽然当你了解其他概念,比如HashMap的工作原理,这个问题变得非常容易,但在我的博客读者中,有很多人正在为初级水平的面试或工作做准备,所以我决定总结一下HashMap和Hashtable之间的区别的知识。
1.HashMap和Hashtable之间的区别
1.1. 同步性
Hashtable是同步的(即在Hashtable内定义的方法是同步的),而HashMap不是。如果你想让HashMap线程安全,可以使用Collections.synchronizedMap(map)或ConcurrentHashMap类。
Hashtable内的方法如下定义为同步的:
public synchronized boolean contains(Object obj){ ... }
public synchronized boolean containsKey(Object obj){ ... }
public synchronized Object get(Object obj){ ... }
public synchronized Object put(Object obj, Object obj1){ ... }
public synchronized Object remove(Object obj){ ... }
1.2. 空键
Hashtable不允许空键或空值。HashMap允许一个空键(其他空键将简单地覆盖第一个空键),以及任意数量的空值。
Hashtable<String, String> hashTable = new Hashtable<String, String>();
hashTable.put(null, "value");
//或
hashTable.put("key", null);
输出:
Exception in thread "main" java.lang.NullPointerException
at java.util.Hashtable.hash(Unknown Source)
at java.util.Hashtable.put(Unknown Source)
at test.core.MapExamples.main(MapExamples.java:12)
1.3. 遗留
Hashtable是一个遗留类,不是最初的Java集合框架的一部分(后来在JDK 1.2中包括了它)。HashMap从一开始就是集合的一部分。还要注意的是,Hashtable扩展了Dictionary类,正如Javadocs所述,这是过时的,并已在较新的JDK版本中被Map接口所取代。
//HashTable定义
public class Hashtable extends Dictionary implements Map, Cloneable, Serializable {}
//HashMap定义
public class HashMap extends AbstractMap implements Map, Cloneable, Serializable {}
1.4. 快速失败迭代器
HashMap中的迭代器是快速失败(fail-fast)的,如果其他线程在结构上通过添加或删除任何元素(除了迭代器自己的remove()方法)修改了Map,它会抛出ConcurrentModificationException异常。但这不是一个保证的行为,将由JVM尽力完成。Hashtable的枚举器不是快速失败的。
HashMap<String, String> hashMap = new HashMap<String, String>();
hashMap.put("key1", "value1");
hashMap.put("key2", "value2");
hashMap.put("key3", "value3");
hashMap.put("key4", "value4");
Iterator<String> iterator = hashMap.keySet().iterator();
while(iterator.hasNext()){
iterator.next();
iterator.remove();
System.out.println(hashMap);
}
输出:
{key3=value3, key2=value2, key1=value1}
{key2=value2, key1=value1}
{key1=value1}
{}
1.5. contains()方法
最后,Map修复了Hashtable接口中的一个小缺陷。Hashtable有一个叫做“contains()”的方法(还有“containsValue()”和“containsKey()”),如果Hashtable包含给定值,则返回true。鉴于其名称,你可能期望这个方法在Hashtable包含给定键时返回true,因为键是Hashtable的主要访问机制。
Map接口通过移除这个方法来消除了这种混淆,并只有“containsValue()”和“containsKey()”。
public boolean containsKey(Object obj) {...}
public boolean containsValue(Object obj) {...}
2.何时使用HashMap和Hashtable
几乎没有什么HashMap或其相关类(即LinkedHashMap或ConcurrentHashMap)不能做,而Hashtable可以。因此,在你编写新代码时没有很好的理由使用Hashtable。始终优先使用HashMap而不是Hashtable。
深入研究这个Hashtable是非常困难的。一旦你能够理解上述区别,你就可以使用这两个类(实际上只应该使用HashMap)。对我来说,分析超出以上的点只是浪费时间,所以,我言尽于此。