1. 程式人生 > >HashTable和HashMap實現原理和區別

HashTable和HashMap實現原理和區別

HashTable和HashMap都是map介面的實現類,這兩個類的實現原理基本是一致的,都是基於陣列加連結串列的資料結構

一、實現原理:

HashTable和HashMap都實現了map介面,只是HashTable繼承了Dictionary抽象類而HashMap繼承了AbstractMap類,他們的底層實現基本是一致的,都是基於陣列(Entry型別)加連結串列這種資料結構實現的

1、HashTable和HashMap的構造方法:二者的構造方法都是一樣的,有以下4中(以HashMap為例)

構造一個空的 HashMap ,預設初始容量(16)和預設負載係數(0.75)。

HashMap(int initialCapacity)

構造一個空的 HashMap具有指定的初始容量和預設負載因子(0.75)。

HashMap(int initialCapacity, float loadFactor)

構造一個空的 HashMap具有指定的初始容量和負載因子。

HashMap(Map<? extends K,? extends V> m)

構造一個新的 HashMap與指定的相同的對映 Map 。

HashMap的一個例項有兩個影響其效能的引數: 初始容量(initialCapacity負載因子

loadFactor) 。 容量是雜湊表中的桶(bucket)數,初始容量只是建立雜湊表時的容量。 負載因子是在容量自動增加之前允許雜湊表得到滿足的度量。 當在散列表中的條目的數量超過了負載因數和初始容量的乘積,雜湊表被重新雜湊 (即,內部資料結構被重建),使得雜湊表具有桶的大約兩倍。

作為一般規則,預設負載因子(.75)提供了時間和空間成本之間的良好折中。 更高的值會降低空間開銷,但會增加查詢成本(反映在HashMap類的大部分操作中,包括get和put )。

HashTable

  • 底層陣列+連結串列實現,無論key還是value都不能為null,執行緒安全,實現執行緒安全的方式是在修改資料時鎖住整個HashTable,效率低,ConcurrentHashMap做了相關優化
  • 初始size為11,擴容:newsize = olesize*2+1
  • 計算index的方法:index = (hash & 0x7FFFFFFF) % tab.length

HashMap

  • 底層陣列+連結串列實現,可以儲存null鍵和null值,執行緒不安全
  • 初始size為16,擴容:newsize = oldsize*2,size一定為2的n次冪
  • 擴容針對整個Map,每次擴容時,原來陣列中的元素依次重新計算存放位置,並重新插入
  • 插入元素後才判斷該不該擴容,有可能無效擴容(插入後如果擴容,如果沒有再次插入,就會產生無效擴容)
  • 當Map中元素總數超過Entry陣列的75%,觸發擴容操作,為了減少連結串列長度,元素分配更均勻
  • 計算index方法:index = hash & (tab.length – 1)

HashMap的初始值還要考慮載入因子:

  •  雜湊衝突:若干Key的雜湊值按陣列大小取模後,如果落在同一個陣列下標上,將組成一條Entry鏈,對Key的查詢需要遍歷Entry鏈上的每個元素執行equals()比較。
  • 載入因子:為了降低雜湊衝突的概率,預設當HashMap中的鍵值對達到陣列大小的75%時,即會觸發擴容。因此,如果預估容量是100,即需要設定100/0.75=134的陣列大小。
  • 空間換時間:如果希望加快Key查詢的時間,還可以進一步降低載入因子,加大初始大小,以降低雜湊衝突的概率。

HashMap和Hashtable都是用hash演算法來決定其元素的儲存,因此HashMap和Hashtable的hash表包含如下屬性:

  • 容量(capacity):hash表中桶的數量
  • 初始化容量(initial capacity):建立hash表時桶的數量,HashMap允許在構造器中指定初始化容量
  • 尺寸(size):當前hash表中記錄的數量
  • 負載因子(load factor):負載因子等於“size/capacity”。負載因子為0,表示空的hash表,0.5表示半滿的散列表,依此類推。輕負載的散列表具有衝突少、適宜插入與查詢的特點(但是使用Iterator迭代元素時比較慢)

二.HashMap和Hashtable的區別

HashMap和Hashtable都實現了Map介面,但決定用哪一個之前先要弄清楚它們之間的分別。主要的區別有:執行緒安全性,同步(synchronization),以及速度。

  1. HashMap幾乎可以等價於Hashtable,除了HashMap是非synchronized的,並可以接受null(HashMap可以接受為null的鍵值(key)和值(value),而Hashtable則不行)。
  2. HashMap是非synchronized,而Hashtable是synchronized,這意味著Hashtable是執行緒安全的,多個執行緒可以共享一個Hashtable;而如果沒有正確的同步的話,多個執行緒是不能共享HashMap的。Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的擴充套件性更好。
  3. 另一個區別是HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以當有其它執行緒改變了HashMap的結構(增加或者移除元素),將會丟擲ConcurrentModificationException,但迭代器本身的remove()方法移除元素則不會丟擲ConcurrentModificationException異常。但這並不是一個一定發生的行為,要看JVM。這條同樣也是Enumeration和Iterator的區別。
  4. 由於Hashtable是執行緒安全的也是synchronized,所以在單執行緒環境下它比HashMap要慢。如果你不需要同步,只需要單一執行緒,那麼使用HashMap效能要好過Hashtable。
  5. HashMap不能保證隨著時間的推移Map中的元素次序是不變的。

我們能否讓HashMap同步?

HashMap可以通過下面的語句進行同步:
Map m = Collections.synchronizeMap(hashMap);

HashSet和HashMap的區別

*HashMap* *HashSet*
HashMap實現了Map介面 HashSet實現了Set介面
HashMap儲存鍵值對 HashSet僅僅儲存物件
使用put()方法將元素放入map中 使用add()方法將元素放入set中
HashMap中使用鍵物件來計算hashcode值 HashSet使用成員物件來計算hashcode值,對於兩個物件來說hashcode可能相同,所以equals()方法用來判斷物件的相等性,如果兩個物件不同的話,那麼返回false
HashMap比較快,因為是使用唯一的鍵來獲取物件 HashSet較HashMap來說比較慢

相關推薦

HashTableHashMap實現原理區別

HashTable和HashMap都是map介面的實現類,這兩個類的實現原理基本是一致的,都是基於陣列加連結串列的資料結構 一、實現原理: HashTable和HashMap都實現了map介面,只是HashTable繼承了Dictionary抽象類而HashMap繼承了A

HashMap實現原理源碼分析

aci 鍵值對 creat 變化 遍歷數組 沖突的解決 查看 seed 二分 作者: dreamcatcher-cx 出處: <http://www.cnblogs.com/chengxiao/>原文:https://www.cnblogs.com/cheng

jdk7中hashmap實現原理jdk8中hashmap的改進方法總結

原文連結:http://blog.csdn.net/vking_wang/article/details/141665931. HashMap的資料結構資料結構中有陣列和連結串列來實現對資料的儲存,但這兩者基本上是兩個極端。      陣列陣列儲存區間是連續的,佔用記憶體嚴重

Java1.7 HashMap 實現原理源碼分析

時間復雜度 異或 n) eof www. pub 並發訪問 子類 安全 HashMap 源碼分析是面試中常考的一項,下面一篇文章講得很好,特地轉載過來。 本文轉自:https://www.cnblogs.com/chengxiao/p/6059914.html

面試題 —— HashMapHashTable、HashSet的實現原理底層資料結構

HashMap和Hashtable的區別 兩者最主要的區別在於Hashtable是執行緒安全,而HashMap則非執行緒安全 Hashtable的實現方法裡面都添加了synchronized關鍵字來確保執行緒同步,因此相對而言HashMap效能會高一些,我們平時使

HashMap實現原理底層結構 圖解+原始碼分析

 雜湊表(hash table)也叫散列表,是一種非常重要的資料結構,應用場景及其豐富,許多快取技術(比如memcached)的核心其實就是在記憶體中維護一張大的雜湊表,而HashMap的實現原理也常常出現在各類的面試題中,重要性可見一斑。本文會對java集合框架中的對應實現HashMap的實現原理

演算法---hash演算法原理(java中HashMap底層實現原理原始碼解析)

散列表(Hash table,也叫雜湊表),是依據關鍵碼值(Key value)而直接進行訪問的資料結構。也就是說,它通過把關鍵碼值對映到表中一個位置來訪問記錄,以加快查詢的速度。這個對映函式叫做雜湊函式,存放記錄的陣列叫做散列表。  比如我們要儲存八十八個資料,我們為他申請了100個

HashMap實現原理底層結構

memcached 結點 文章 actor lse get方法 會有 power 整體 哈希表(hash table)也叫散列表,是一種非常重要的數據結構,應用場景及其豐富,許多緩存技術(比如memcached)的核心其實就是在內存中維護一張大的哈希表,而HashMap的實

StringBuffer與StringBuilder的區別實現原理擴容

StringBuffer與StringBuilder的區別,及實現原理 區別 1、StringBuffer 與 StringBuilder 中的方法和功能完全是等價的, 2、只是StringBuffer 中的方法大都採用了 synchronized 

HashMap底層實現原理擴容

hashmap底層實現和擴容以及改寫hashcode和equals方法 基於jdk1.7 …jdk1.8之後加了紅黑樹,想看jdk1.8實現的,請另行Google! Hashmap是一種非常常用的、應用廣泛的資料型別,最近研究到相關的內容,就正好複

HashMap實現原理,利用陣列連結串列儲存元素

陣列:儲存區間連續,佔用記憶體嚴重,定址容易,插入刪除困難 連結串列:儲存區間離散,佔用記憶體比較寬鬆,定址困難,插入刪除容易 hashmap綜合應用了這兩種資料結構,實現了定址容易,插入刪除也容易 HashMap結構示意圖: 實現原理:用一個數組來儲存元素,但是這

ArrayListlinkedList底層實現原理以及區別

ArrayList 先說說Arraylist,Arraylist是基於動態陣列實現的,所以查詢速度快,但是增刪操作的速度會比較慢,但是為什麼會這樣?我解釋一下動態陣列,基本就可以明白這個問題了。 先說說靜態陣列是怎麼來儲存資料的,當我們使用new來建立一個數組,實際上是在

HashMapHashtable區別HashMap實現原理

    Map是編碼過程中經常使用到的容器,而HashMap和Hashtable都實現了Map的,所以我們往往會把兩者進行對比。 HashMap和Hashtable區別 Hashtable是執行緒安全的,HashMap是非執行緒安全的。Hashtable是基於老的Diact

[Go] sync.Pool 的實現原理 適用場景

臨時 digg 簡單的 設置 com 運行 之前 結果 官方文檔 摘錄一: Go 1.3 的 sync 包中加入一個新特性:Pool。 官方文檔可以看這裏 http://golang.org/pkg/sync/#Pool 這個類設計的目的是用來保存和復用臨時對象,以減

Java並發機制底層實現原理

差距 32處理器 們的 trac 結點 exce jdk cep 定性   Java代碼在編譯後會變成Java字節碼,字節碼被類加載器加載到JVM裏,JVM執行字節碼轉化為匯編指令在CPU上執行。Java中的並發機制依賴於JVM的實現和CPU的指令。      Java語言

磁共振中的T1, T2 T2*的原理區別

down 90度 沒有 fonts 過程 因此 idt tex 狀態 轉自:http://blog.csdn.net/taigw/article/details/44834953 從物理的角度,要理解這幾個概念的區別,需要對原子核的磁化有所了解,本文通過一些圖示對這幾個概

HashMapHashtable、ConcurrentHashMap的原理區別

另一個 cnblogs 需要 構造器 新的 底層 bsp 哈希 fas HashTable 底層數組+鏈表實現,無論key還是value都不能為null,線程安全,實現線程安全的方式是在修改數據時鎖住整個HashTable,效率低,ConcurrentHashMap做了相

STL原始碼剖析——stack的實現原理使用方法詳解

Stack 簡介     stack 是堆疊容器,是一種“先進後出”的容器。     stack 是簡單地裝飾 deque 容器而成為另外一種容器。     使用 stack 時需要加上標頭檔案 #include<s

STL原始碼剖析——deque的實現原理使用方法詳解

Deque 簡介     deque是“double—ended queue”的縮寫,和vector一樣都是STL的容器,deque 是雙端陣列,而 vector 是單端的。     deque 在介面上和 vector 非常相似,在許多操作的地方

JMM底層實現原理

現代計算機物理上的記憶體模型 物理機遇到的併發問題與虛擬機器中的情況有不少相似之處,物理機對併發的處理方案對於虛擬機器的實現也有相當大的參考意義。 其中一個重要的複雜性來源是絕大多數的運算任務都不可能只靠處理器“計算”就能完成,處理器至少要與記憶體互動,如讀取運算資料、儲存運算結果