簡體   English   中英

Java 中的 HashMap 和 Hashtable 有什么區別?

[英]What are the differences between a HashMap and a Hashtable in Java?

Java 中的HashMapHashtable有什么區別?

哪個對於非線程應用程序更有效?

Java中HashMapHashtable有幾個區別:

  1. Hashtablesynchronized ,而HashMap不是。 這使得HashMap更適合非線程應用程序,因為未同步的對象通常比同步的對象執行得更好。

  2. Hashtable不允許null鍵或值。 HashMap允許一個null鍵和任意數量的null值。

  3. HashMap 的子類之一是LinkedHashMap ,因此如果您想要可預測的迭代順序(默認情況下是插入順序),您可以輕松地將HashMap換成LinkedHashMap 如果您使用Hashtable這將不會那么容易。

由於同步對您來說不是問題,我建議使用HashMap 如果同步成為一個問題,您還可以查看ConcurrentHashMap

請注意,很多答案都表明 Hashtable 是同步的。 在實踐中,這給你帶來的影響很小。 同步是在訪問器/修改器方法上,將阻止兩個線程同時添加或從映射中刪除,但在現實世界中,您經常需要額外的同步。

一個非常常見的習慣用法是“先檢查再放”——即在Map查找條目,如果它不存在則添加它。 無論您使用Hashtable還是HashMap這都不是原子操作。

可以通過以下方式獲得等效同步的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被認為是遺留代碼。 沒有什么有關的Hashtable不能用做HashMap或派生HashMap ,因此對於新的代碼,我看不到回去的任何理由Hashtable

這個問題在面試中經常被問到,以檢查候選人是否理解集合類的正確用法,以及是否知道可用的替代解決方案。

  1. HashMap類大致等同於Hashtable ,除了它是非同步的並且允許空值。 HashMap允許 null 值作為鍵和值,而Hashtable不允許null s)。
  2. HashMap不保證映射的順序會隨着時間的推移保持不變。
  3. HashMap是非同步的,而Hashtable是同步的。
  4. HashMap迭代器是故障安全的,而Hashtable的枚舉器則不是,如果任何其他線程通過添加或刪除除Iterator自己的remove()方法之外的任何元素在結構上修改映射,則拋出ConcurrentModificationException 但這不是保證的行為,JVM 會盡最大努力完成。

一些重要術語的注意事項:

  1. 同步意味着只有一個線程可以在一個時間點修改哈希表。 基本上,這意味着在對Hashtable執行更新之前,任何線程都必須獲取對象上的鎖,而其他線程將等待釋放鎖。
  2. 故障安全在迭代器的上下文中是相關的。 如果在集合對象上創建了迭代器,並且某個其他線程嘗試“結構化”修改集合對象,則會引發並發修改異常。 盡管其他線程可以調用set方法,因為它不會“從結構上”修改集合。 但是,如果在調用set之前,集合已在結構上進行了修改,則會拋出IllegalArgumentException
  3. 結構修改是指刪除或插入可以有效改變地圖結構的元素。

HashMap可以通過以下方式同步

Map m = Collections.synchronizeMap(hashMap);

Map 提供 Collection 視圖,而不是通過 Enumeration 對象直接支持迭代。 集合視圖極大地增強了界面的表現力,本節稍后將對此進行討論。 Map 允許您迭代鍵、值或鍵值對; Hashtable不提供第三個選項。 Map 提供了一種在迭代過程中刪除條目的安全方法; Hashtable沒有。 最后,Map 修復了Hashtable接口中的一個小缺陷。 Hashtable有一個稱為 contains 的方法,如果Hashtable包含給定值,則返回 true。 鑒於其名稱,如果Hashtable包含給定的鍵,您會期望此方法返回 true,因為鍵是Hashtable的主要訪問機制。 Map 接口通過重命名方法containsValue消除了這種混淆。 此外,這提高了接口的一致性—— containsValue並行containsKey

地圖界面

HashMapMap接口的一個實現,它使用哈希碼來索引一個數組。 Hashtable :嗨,1998 年打電話。 他們希望恢復他們的集合 API。

不過說真的,你最好完全遠離Hashtable 對於單線程應用程序,您不需要額外的同步開銷。 對於高度並發的應用程序,偏執的同步可能會導致飢餓、死鎖或不必要的垃圾收集暫停。 就像 Tim Howland 指出的那樣,您可以改用ConcurrentHashMap

請記住,在引入 Java Collections Framework (JCF) 之前, HashTable是遺留類,后來經過改造以實現Map接口。 VectorStack

因此,在新代碼中始終遠離它們,因為正如其他人指出的那樣,JCF 中總是有更好的選擇

這是您會發現有用的Java 集合備忘單 請注意,灰色塊包含遺留類 HashTable、Vector 和 Stack。

在此處輸入圖片說明

已經發布了許多好的答案。 我正在添加一些新觀點並對其進行總結。

HashMapHashtable都用於以鍵值形式存儲數據 兩者都使用散列技術來存儲唯一鍵。 但是下面給出的 HashMap 和 Hashtable 類之間存在許多差異。

哈希表

  1. HashMap是非同步的。 它不是線程安全的,如果沒有適當的同步代碼,就不能在許多線程之間共享。
  2. HashMap允許一個空鍵和多個空值。
  3. HashMap是 JDK 1.2 中引入的一個新類。
  4. HashMap很快。
  5. 我們可以通過調用此代碼使HashMap同步
    Map m = Collections.synchronizedMap(HashMap);
  6. HashMap被迭代器遍歷。
  7. HashMap迭代器是快速失敗的。
  8. HashMap繼承了 AbstractMap 類。

哈希表

  1. Hashtable是同步的。 它是線程安全的,可以與多個線程共享。
  2. Hashtable不允許空鍵或值。
  3. Hashtable是一個遺留類。
  4. Hashtable很慢。
  5. Hashtable是內部同步的,不能不同步。
  6. Hashtable由 Enumerator 和 Iterator 遍歷。
  7. Hashtable枚舉器不是快速失敗的。
  8. Hashtable繼承了 Dictionary 類。

進一步閱讀Java 中的 HashMap 和 Hashtable 有什么區別?

在此處輸入圖片說明

看看這張圖表。 它提供了不同數據結構之間的比較以及HashMapHashtable 比較准確、清晰且易於理解。

Java 集合矩陣

除了 izb 所說的, HashMap允許空值,而Hashtable不允許。

另請注意, Hashtable擴展了Dictionary類,作為Javadocs狀態,該類已過時並已被Map接口取代。

HashtableHashMap類似,具有類似的接口。 建議您使用HashMap ,除非您需要支持遺留應用程序或需要同步,因為Hashtables方法是同步的。 因此,在您不是多線程的情況下, HashMaps是您最好的選擇。

Hashtable是同步的,而HashMap不是。 這使得HashtableHashmap慢。

對於單線程應用程序,請使用HashMap因為它們在功能方面是相同的。

hashtable 和 hashmap 之間的另一個主要區別是 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 中,我們還承諾能夠像使用古老的腳本語言一樣構造和訪問 HashMap:

Map<String,Integer> map = { "orange" : 12, "apples" : 15 };
map["apples"];

更新:不,他們不會在 1.8 中登陸... :(

Project Coin 的收藏增強功能是否會出現在 JDK8 中?

  • HashTable是同步的,如果您在單線程中使用它,您可以使用HashMap ,這是一個非同步版本。 未同步的對象通常性能更高一些。 順便說一下,如果多個線程並發訪問一個HashMap,並且至少有一個線程在結構上修改了映射,則必須在外部進行同步。 您可以使用以下方法將未同步的地圖包裝在同步地圖中:

     Map m = Collections.synchronizedMap(new HashMap(...));
  • HashTable 只能包含非空對象作為鍵或值。 HashMap 可以包含一個空鍵和一個空值。

  • Map 返回的迭代器是快速失敗的,如果在迭代器創建后的任何時間對映射進行結構修改,除了通過迭代器自己的 remove 方法之外的任何方式,迭代器都會拋出ConcurrentModificationException 因此,面對並發修改,迭代器快速而干凈地失敗,而不是在未來不確定的時間冒着任意、非確定性行為的風險。 由 Hashtable 的鍵和元素方法返回的枚舉不是快速失敗的。

  • HashTable 和 HashMap 是Java Collections Framework 的成員(從 Java 2 平台 v1.2 開始,HashTable 被改造以實現 Map 接口)。

  • HashTable 被認為是遺留代碼,如果需要線程安全的高並發實現,文檔建議使用ConcurrentHashMap代替 Hashtable。

  • HashMap 不保證元素返回的順序。 對於 HashTable 我猜它是一樣的,但我不完全確定,我沒有找到明確說明的資源。

HashMapHashtable也有顯着的算法差異。 之前沒有人提到過這一點,所以這就是我提出它的原因。 HashMap將構建一個大小為 2 次方的哈希表,動態增加它,以便在任何存儲桶中最多有大約 8 個元素(沖突),並且對於一般元素類型將非常好地攪動元素。 但是,如果您知道自己在做什么,則Hashtable實現可以更好地控制散列,即您可以使用例如最接近您的值域大小的素數來修復表大小,這將導致比 HashMap 更好的性能,即更少某些情況下的碰撞。

除了這個問題中廣泛討論的明顯差異之外,我將 Hashtable 視為“手動驅動”汽車,您可以更好地控制散列,而 HashMap 作為“自動驅動”對應物,通常性能良好。

根據這里的信息,我建議使用 HashMap。 我認為最大的優點是 Java 會阻止你在迭代時修改它,除非你通過迭代器來做。

Collection ——有時也稱為容器——只是一個將多個元素組合成一個單元的對象。 Collection用於存儲、檢索、操作和交流聚合數據。 集合框架W是用於表示和操作集合的統一架構。

HashMap JDK1.2和 Hashtable JDK1.0都用於表示一組以<Key, Value>對表示的對象。 每個<Key, Value>對稱為Entry對象。 Entries 的集合由HashMapHashtable的對象引用。 集合中的鍵必須是唯一的或獨特的。 [因為它們用於檢索特定鍵的映射值。 集合中的值可以重復。]


«超類、遺留和集合框架成員

Hashtable 是JDK1.0引入的遺留類,是Dictionary 類的子類。 JDK1.2重新設計Hashtable,實現Map接口,成為集合框架的成員。 HashMap 從它在JDK1.2引入開始就是 Java Collection Framework 的成員。 HashMap 是 AbstractMap 類的子類。

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 { ... }

«初始容量和負載系數

容量是哈希表中的桶數,初始容量就是哈希表創建時的容量。 注意哈希表是開放的:在“ hash collision ”的情況下,單個桶存儲多個條目,必須順序搜索。 負載因子是衡量哈希表在其容量自動增加之前允許達到多滿的指標。

HashMap 使用默認初始容量(16)和默認負載因子(0.75)構造一個空哈希表。 其中 Hashtable 構造具有默認初始容量(11)和負載因子/填充率 (0.75) 的空哈希表。

哈希映射和哈希表

«發生哈希沖突時的結構修改

HashMapHashtable在哈希沖突的情況下,它們將映射條目存儲在鏈表中。 從 Java8 for HashMap如果哈希桶增長超過某個閾值,該桶將從linked list of entries to a balanced tree切換linked list of entries to a balanced tree 將最壞情況的性能從 O(n) 提高到 O(log n)。 在將列表轉換為二叉樹時,哈希碼用作分支變量。 如果在同一個桶中有兩個不同的哈希碼,一個被認為更大並且在樹的右邊,另一個在左邊。 但是當兩個哈希碼相等時, HashMap假設鍵是可比較的,並比較鍵來確定方向,以便可以保持某種順序。 使HashMap的鍵具有可比性是一個很好的做法。 如果桶大小達到TREEIFY_THRESHOLD = 8則在添加條目時將條目的TREEIFY_THRESHOLD = 8轉換為平衡樹,在刪除小於TREEIFY_THRESHOLD且最多UNTREEIFY_THRESHOLD = 6的條目時,會將平衡樹重新轉換為條目的鏈表。 Java 8 SRC堆棧

«集合視圖迭代,Fail-Fast 和 Fail-Safe

    +--------------------+-----------+-------------+
    |                    | Iterator  | Enumeration |
    +--------------------+-----------+-------------+
    | Hashtable          | fail-fast |    safe     |
    +--------------------+-----------+-------------+
    | HashMap            | fail-fast | fail-fast   |
    +--------------------+-----------+-------------+
    | ConcurrentHashMap  |   safe    |   safe      |
    +--------------------+-----------+-------------+

Iterator本質上是快速失敗的。 即,如果在迭代時修改集合而不是它自己的 remove() 方法,它會拋出 ConcurrentModificationException。 Enumeration本質上是故障安全的。 如果在迭代時修改了集合,它不會拋出任何異常。

根據 Java API Docs,Iterator 總是優於 Enumeration。

注意:枚舉接口的功能由迭代器接口復制。 此外,Iterator 添加了一個可選的刪除操作,並具有較短的方法名稱。 新的實現應該考慮使用 Iterator 而不是 Enumeration。

Java 5 中引入了 ConcurrentMap 接口ConcurrentHashMap - 一個由哈希表支持的高並發、高性能ConcurrentMap實現。 此實現在執行檢索時從不阻塞,並允許客戶端選擇更新的並發級別。 它旨在替代Hashtable :除了實現ConcurrentMap ,它還支持Hashtable特有的所有“遺留”方法。

  • 每個HashMapEntry的值都是可變的,從而確保競爭修改和后續讀取的細粒度一致性; 每次讀取都反映了最近完成的更新

  • 迭代器和枚舉是故障安全的——反映自迭代器/枚舉創建以來某個時刻的狀態; 這允許以降低一致性為代價的同時讀取和修改。 它們不會拋出 ConcurrentModificationException。 然而,迭代器被設計為一次只能被一個線程使用。

  • Hashtable類似但與HashMap不同的是,此類不允許將 null 用作鍵或值。

public static void main(String[] args) {

    //HashMap<String, Integer> hash = new HashMap<String, Integer>();
    Hashtable<String, Integer> hash = new Hashtable<String, Integer>();
    //ConcurrentHashMap<String, Integer> hash = new ConcurrentHashMap<>();
    
    new Thread() {
        @Override public void run() {
            try {
                for (int i = 10; i < 20; i++) {
                    sleepThread(1);
                    System.out.println("T1 :- Key"+i);
                    hash.put("Key"+i, i);
                }
                System.out.println( System.identityHashCode( hash ) );
            } catch ( Exception e ) {
                e.printStackTrace();
            }
        }
    }.start();
    new Thread() {
        @Override public void run() {
            try {
                sleepThread(5);
                // ConcurrentHashMap  traverse using Iterator, Enumeration is Fail-Safe.
                
                // Hashtable traverse using Enumeration is Fail-Safe, Iterator is Fail-Fast.
                for (Enumeration<String> e = hash.keys(); e.hasMoreElements(); ) {
                    sleepThread(1);
                    System.out.println("T2 : "+ e.nextElement());
                }
                
                // HashMap traverse using Iterator, Enumeration is Fail-Fast.
                /*
                for (Iterator< Entry<String, Integer> > it = hash.entrySet().iterator(); it.hasNext(); ) {
                    sleepThread(1);
                    System.out.println("T2 : "+ it.next());
                    // ConcurrentModificationException at java.util.Hashtable$Enumerator.next
                }
                */
                
                /*
                Set< Entry<String, Integer> > entrySet = hash.entrySet();
                Iterator< Entry<String, Integer> > it = entrySet.iterator();
                Enumeration<Entry<String, Integer>> entryEnumeration = Collections.enumeration( entrySet );
                while( entryEnumeration.hasMoreElements() ) {
                    sleepThread(1);
                    Entry<String, Integer> nextElement = entryEnumeration.nextElement();
                    System.out.println("T2 : "+ nextElement.getKey() +" : "+ nextElement.getValue() );
                    //java.util.ConcurrentModificationException at java.util.HashMap$HashIterator.nextNode
                    //                                          at java.util.HashMap$EntryIterator.next
                    //                                          at java.util.Collections$3.nextElement
                }
                */
            } catch ( Exception e ) {
                e.printStackTrace();
            }
        }
    }.start();
    
    Map<String, String> unmodifiableMap = Collections.unmodifiableMap( map );
    try {
        unmodifiableMap.put("key4", "unmodifiableMap");
    } catch (java.lang.UnsupportedOperationException e) {
        System.err.println("UnsupportedOperationException : "+ e.getMessage() );
    }
}
static void sleepThread( int sec ) {
    try {
        Thread.sleep( 1000 * sec );
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

«空鍵和空值

HashMap允許最多一個空鍵和任意數量的空值。 由於Hashtable甚至不允許單個空鍵和空值,如果鍵或值為空,則它會拋出 NullPointerException。 示例

«同步,線程安全

Hashtable是內部同步的。 因此,在多線程應用中使用Hashtable是非常安全的。 因為HashMap不是內部同步的。 因此,在沒有外部同步的多線程應用中使用HashMap是不安全的。 您可以使用Collections.synchronizedMap()方法從外部同步HashMap

«性能

由於Hashtable是內部同步的,這使得HashtableHashMap稍慢。


@見

對於線程應用程序,您通常可以使用 ConcurrentHashMap - 取決於您的性能要求。

1. HashmapHashTable都存儲 key 和 value。

2. Hashmap可以存儲一個 key 為null Hashtable不能存儲null

3、 HashMap不同步, Hashtable同步。

HashMap可以與Collection.SyncronizedMap(map)同步

Map hashmap = new HashMap();

Map map = Collections.SyncronizedMap(hashmap);

除了已經提到的差異之外,需要注意的是,從 Java 8 開始, HashMap將每個桶中使用的 Nodes(鏈表)動態替換為 TreeNodes(紅黑樹),這樣即使存在高哈希沖突,最壞的情況當搜索

O(log(n)) for HashMap Vs O(n) in Hashtable

*上述改進尚未應用於Hashtable ,而僅應用於HashMapLinkedHashMapConcurrentHashMap

僅供參考,目前,

  • TREEIFY_THRESHOLD = 8 :如果一個bucket包含8個以上的節點,則鏈表轉化為平衡樹。
  • UNTREEIFY_THRESHOLD = 6 :當桶變得太小(由於移除或調整大小)時,樹將轉換回鏈表。

HashTable 和 HashMaps 有 5 個基本區別。

  1. Maps 允許您迭代和檢索鍵、值以及鍵值對,而 HashTable 沒有所有這些功能。
  2. 在Hashtable中有一個函數contains(),使用起來很混亂。 因為contains 的意思稍有偏差。 是表示包含鍵還是包含值? 很難理解。 Maps 中同樣的事情我們有 ContainsKey() 和 ContainsValue() 函數,它們很容易理解。
  3. 在 hashmap 中,您可以在迭代時安全地刪除元素。 因為它在哈希表中是不可能的。
  4. HashTables 默認是同步的,所以它可以很容易地與多個線程一起使用。 由於默認情況下 HashMap 不同步,因此只能與單線程一起使用。 但是您仍然可以使用 Collections util 類的 synchronizedMap(Map m) 函數將 HashMap 轉換為 synchronized。
  5. HashTable 不允許空鍵或空值。 其中 HashMap 允許一個空鍵和多個空值。

我的小貢獻:

  1. HashtableHashMap第一個也是最顯着的區別是, HashMap不是線程安全的,而Hashtable是線程安全的集合。

  2. HashtableHashMap之間的第二個重要區別是性能,因為HashMap不是同步的,它比Hashtable性能更好。

  3. HashtableHashMap第三個區別是Hashtable是過時的類,您應該使用ConcurrentHashMap代替 Java 中的Hashtable

HashMap:它是 java.util 包中可用的一個類,用於以鍵和值格式存儲元素。

Hashtable:它是一個遺留類,在集合框架內被識別。

  1. Hashtable是同步的,而HashMap不是。
  2. 另一個區別是HashMap中的迭代器是故障安全的,而Hashtable的枚舉器則不是。 如果您在迭代時更改地圖,您就會知道。
  3. HashMap允許其中包含空值,而Hashtable則不允許。

HashTable是 jdk 中的遺留類,不應再使用。 ConcurrentHashMap替換它的用法。 如果您不需要線程安全,請使用HashMap ,它不是線程安全的,但速度更快且使用更少的內存。

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。

Hashtable:

哈希表是一種保留鍵值對值的數據結構。 它不允許鍵和值都為 null。 如果添加 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類似於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));

    }
}

HashMapHashtable都用於以鍵值形式存儲數據。 兩者都使用散列技術來存儲唯一鍵。 下面給出了 HashMap 和 Hashtable 類之間的許多差異。

在此處輸入圖片說明

古老而經典的話題,只想添加這個有用的博客來解釋這一點:

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 集合框架的成員。

  1. HashMap 和 Hashtable 的主要區別之一是 HashMap 是非同步的,而 Hashtable 是同步的,這意味着 Hashtable 是線程安全的,可以在多個線程之間共享,但 HashMap 不能在沒有適當同步的情況下在多個線程之間共享。 Java 5 引入了 ConcurrentHashMap,它是 Hashtable 的替代品,提供比 Java 中的 Hashtable 更好的可擴展性。同步意味着在一個時間點只有一個線程可以修改哈希表。 基本上,這意味着在對哈希表執行更新之前,任何線程都必須獲取對象上的鎖,而其他線程將等待釋放鎖。

  2. HashMap 類大致等同於 Hashtable,除了它允許空值。 (HashMap 允許空值作為鍵和值,而 Hashtable 不允許空值)。

  3. HashMap 與 Hashtable 之間的第三個顯着區別是 HashMap 中的 Iterator 是一個快速失敗的迭代器,而 Hashtable 的枚舉器不是,如果任何其他線程通過添加或刪除除迭代器自己的元素之外的任何元素在結構上修改映射,則拋出 ConcurrentModificationException ) 方法。 但這不是保證的行為,JVM 會盡最大努力完成。 這也是Java中Enumeration和Iterator的一個重要區別。

  4. Hashtable 和 HashMap 之間更顯着的區別是,由於線程安全和同步,如果在單線程環境中使用,Hashtable 比 HashMap 慢得多。 因此,如果您不需要同步並且 HashMap 僅由一個線程使用,那么它在 Java 中執行 Hashtable。

  5. HashMap 不保證映射的順序會隨着時間的推移保持不變。

請注意,HashMap 可以通過以下方式同步

Map m = Collections.synchronizedMap(hashMap);

總而言之,Java 中的 Hashtable 和 HashMap 之間存在顯着差異,例如線程安全和速度,並且僅在您絕對需要線程安全時才使用 Hashtable,如果您正在運行 Java 5,請考慮在 Java 中使用 ConcurrentHashMap。

HashMap是模擬的,因此可以在GWT client code使用,而Hashtable則不是。

HashMaps使您可以自由進行同步,調試更加輕松

由於Java中的Hashtable是Dictionary類的子類,由於Map接口的存在,現在已經過時,不再使用。 此外,對於實現 Map Interface 的類,您可以使用 Hashtable 執行任何操作。

同步或線程安全

哈希映射未同步,因此不安全,並且在沒有適當的同步塊的情況下無法在多個線程之間共享,而哈希表已同步,因此是線程安全的。

空鍵和空值

HashMap允許一個null鍵和任意數量的null值。Hashtable不允許null鍵或值。

迭代值

HashMap中的Iterator是一個快速失敗的迭代器,而Hashtable的枚舉器則不是,如果其他線程通過添加或刪除Iterator自己的remove()方法之外的任何元素在結構上修改映射,則Hashtable的枚舉器將拋出ConcurrentModificationException。

超類和遺產

HashMap是AbstractMap類的子類,而Hashtable是Dictionary類的子類。

性能

由於HashMap不同步,因此與Hashtable相比,速度更快。

請參閱http://modernpathshala.com/Article/1020/difference-between-hashmap-and-hashtable-in-java中的示例以及與Java集合有關的訪談問題和測驗

HashMap 是一個用於以鍵和值格式存儲元素的類。它不是線程安全的。 因為它不是同步的。因為 Hashtable 是同步的。Hashmap 允許為空,但 hastable 不允許為空。

Hashtable 類是同步的,也就是說,它旨在供處理多線程或多線程進程的應用程序使用。 在應用程序到進程的經典情況下,同步類的效率較低,因此 Hashmap 類通常更快。 HashTable 類不接受 Null 值,無論是鍵還是值,而 HashMap 類允許單個鍵為 Null 並盡可能多地為 null。

Hashtable 是線程安全的,可以在應用程序中的多個線程之間共享。

另一方面,HashMap 不是同步的,如果沒有額外的同步代碼,就不能被多個線程訪問。 我們可以使用Collections.synchronizedMap()來制作 HashMap 的線程安全版本。 我們也可以創建自定義鎖定代碼或使用 synchronized 關鍵字使代碼成為線程安全的。

HashMap 不是同步的,因此它比 Hashtable 更快並且使用更少的內存。 通常,在單線程應用程序中,未同步的對象比同步的對象要快。

Hashtable 根本不允許 null。

我們應該將 HashMap 用於非同步或單線程應用程序。

從 JDK 1.8 開始,Hashtable 已被棄用。 然而,ConcurrentHashMap 是一個很好的 Hashtable 替代品。 我們應該考慮在具有多線程的應用程序中使用 ConcurrentHashMap。

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

哈希圖與哈希表

  1. HashMap 是非同步的。 它不是線程安全的,如果沒有適當的同步代碼,就不能在許多線程之間共享,而 Hashtable 是同步的。 它是線程安全的,可以與多個線程共享。
  2. HashMap 允許一個空鍵和多個空值,而 Hashtable 不允許任何空鍵或值。
  3. 如果不需要線程同步,HashMap 通常優於 HashTable 為什么 HashTable 不允許 null 而 HashMap 呢? 要成功地從 HashTable 存儲和檢索對象,用作鍵的對象必須實現 hashCode 方法和 equals 方法。 由於 null 不是對象,因此無法實現這些方法。 HashMap 是對 Hashtable 的高級版本和改進。 HashMap 是后來創建的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM