HashMap
和Hashtable
两个类都是实现的Map接口,它们都是保存键值(key-value
)对。
可以从以下几个方面来比较两者的不同:
继承的父类不同
Hashtable
继承自Dictionary
类,而HashMap
继承自AbstractMap
类。但二者都实现了Map
接口。
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
线程安全性不同
Hashtable
中的方法是Synchronize
的,而HashMap
中的方法在缺省情况下是非Synchronize
的。在多线程并发的环境下,可以直接使用Hashtable
,不需要自己为它的方法实现同步,但使用HashMap
时就必须要自己增加同步处理。这意味着Hashtable
是线程安全的,多个线程可以共享一个Hashtable
;而如果没有正确的同步的话,多个线程是不能共享HashMap
的。Java 5
提供了ConcurrentHashMap
,它是Hashtable
的替代,比Hashtable
的扩展性更好。
HashMap
可以通过synchronizedMap(HashMap)
方法进行同步。具体实现如下:
import java.util.*;
public class HashMapSynchronization {
public static void main(String[] args) {
// create map
Map<String,String> map = new HashMap<String,String>();
// populate the map
map.put("1","ALIVE ");
map.put("2","IS");
map.put("3","AWESOME");
// create a synchronized map
Map<String,String> syncMap = Collections.synchronizedMap(map);
System.out.println("Synchronized map :"+syncMap);
}
}
是否提供contains方法
HashMap
把Hashtable
的contains
方法去掉了,改成containsValue
和containsKey
,因为contains
方法容易让人引起误解。
Hashtable
则保留了contains
,containsValue
和containsKey
三个方法,其中contains
和containsValue
功能相同。
key和value是否允许null值
其中key
和value
都是对象,并且不能包含重复key
,但可以包含重复的value
。
Hashtable
中,key
和value
都不允许出现null
值。
HashMap
中,null
可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null
。当get()
方法返回null
值时,可能是 HashMap
中没有该键,也可能使该键所对应的值为null
。因此,在HashMap
中不能由get()
方法来判断HashMap
中是否存在某个键, 而应该用containsKey()
方法来判断。
两个遍历方式的内部实现上不同
Hashtable
、HashMap
都使用了Iterator
。而由于历史原因,Hashtable
还使用了Enumeration
的方式 。
hash值不同
哈希值的使用不同,Hashtable
直接使用对象的hashCode
。而HashMap
重新计算hash
值。
内部实现使用的数组初始化和扩容方式不同
Hashtable
中hash
数组默认大小是11
,增加的方式是 old*2+1
。HashMap
中hash
数组的默认大小是16
,而且一定是2
的指数。