關於編程中HashMap和HashTable的選擇問題,我們可以先看看下面這些問題。
歷史問題
Hashtable是個過時的集合類,是基於陳舊的Dictionary類的,並且存在於Java API中很久了。在Java 4中被重寫了,實現了Map接口,所以自此以後也成了Java集合框架中的一部分,而HashMap是Java 1.2引進的Map接口的一個實現。
同步問題
HashMap是非synchronized,而Hashtable是synchronized,這意味着Hashtable是線程安全的,多個線程可以共享一個Hashtable;而如果沒有正確的同步的話,多個線程是不能共享HashMap的。Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的擴展性更好。
迭代問題
HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以當有其它線程改變了HashMap的結構(增加或者移除元素),將會拋出ConcurrentModificationException,但迭代器本身的remove()方法移除元素則不會拋出ConcurrentModificationException異常。但這並不是一個一定發生的行爲,要看JVM。這條同樣也是Enumeration和Iterator的區別。
key值問題
HashMap可以讓你將空值作爲一個表的條目的key或value。HashMap中只有一條記錄可以是一個空的key,但任意數量的條目可以是空的value。這就是說,如果在表中沒有發現搜索鍵,或者如果發現了搜索鍵,但它是一個空的值,那麼get()將返回null。如果有必要,用containKey()方法來區別這兩種情況。
效率問題
由於Hashtable是線程安全的也是synchronized,所以在單線程環境下它比HashMap要慢。如果你不需要同步,只需要單一線程,那麼使用HashMap性能要好過Hashtable。
元素順序
HashMap不能保證隨着時間的推移Map中的元素次序是不變的。
HashMap同步
HashMap可以通過下面的語句進行同步:
Map m = Collections.synchronizeMap(hashMap);
術語解釋
sychronized
sychronized意味着在一次僅有一個線程能夠更改Hashtable。就是說任何線程要更新Hashtable時要首先獲得同步鎖,其它線程要等到同步鎖被釋放之後才能再次獲得同步鎖更新Hashtable。
fail-fast and fail-safe
關於fail-fast and fail-safe,可以參考這篇文章Fail Fast vs Fail Safe
總結
在目前的編程中基本上可以不用HashTable了,在不要求線程安全的情況下直接使用HashMap,效率比較高;如果,要求線程安全,則使用ConcurrentHashMap來代替HashMap。