摘要:經(jīng)過上述討論,我們發(fā)現(xiàn),哈希查找的時(shí)間復(fù)雜度最小沒有沖突是二是什么首先是中的一個(gè)接口。在中,有很多類實(shí)現(xiàn)了接口,就是其中的一個(gè)三是什么是一個(gè)實(shí)現(xiàn)了接口的基于哈希表的類。
我們要想知道HashMap是什么就先要了解Hash和Map是什么
一、Hash是什么
① 哈希查找是一種數(shù)據(jù)結(jié)構(gòu)中用于 查找 的算法,相比于其他查找算法,他的時(shí)間復(fù)雜度更
低,所以在實(shí)際應(yīng)用中大量采取了哈希表的方式,Hashmap就是java內(nèi)置的哈希查找的方法
② 哈希函數(shù)的基本思想: 將記錄的存儲(chǔ)地址和關(guān)鍵字之間建立一個(gè)確定的對(duì)應(yīng)關(guān)系。這樣,當(dāng)想查找某條記錄時(shí),我們根據(jù)記錄的關(guān)鍵字就可以得到它的存儲(chǔ)地址,進(jìn)而快速判斷這條記錄是否存在,存儲(chǔ)在哪里。
③負(fù)載因子:負(fù)載因子是哈希表在其容量自動(dòng)增加之前可以達(dá)到多滿的一種尺度,它衡量的是一個(gè)散列表的空間的使用程度,負(fù)載因子越大表示散列表的裝填程度越高,反之愈小。如果負(fù)載因子越大,對(duì)空間的利用更充分,然而后果是查找效率的降低;如果負(fù)載因子太小,那么散列表的數(shù)據(jù)將過于稀疏,對(duì)空間造成嚴(yán)重浪費(fèi)。hashmap默認(rèn)負(fù)載因子為0.75,一般情況下我們是無需修改的。
④ 哈希函數(shù)的缺陷+改進(jìn)方式: 在哈希存儲(chǔ)中,不同的關(guān)鍵字可能映射到了相同的地址,這就叫產(chǎn)生沖突,我們必須相處沖突處理的方法。當(dāng)然,前輩們已經(jīng)相處了各種各樣的方法,我在這里先不做深究。
⑤ 經(jīng)過上述討論,我們發(fā)現(xiàn),哈希查找的時(shí)間復(fù)雜度最?。]有沖突)是O(1)
二、Map是什么
首先Map是java中的一個(gè)接口。它是java中的一種重要的數(shù)據(jù)結(jié)構(gòu)。
Map是從鍵(關(guān)鍵字)到值(記錄)的映射,鍵不允許重復(fù),每個(gè)鍵最多能映射一個(gè)值。
在java中,有很多類實(shí)現(xiàn)了Map接口,HashMap就是其中的一個(gè)
三、Hashmap是什么
HashMap是一個(gè)實(shí)現(xiàn)了Map接口的基于哈希表的類 。
也就是說,HashMap既有map的鍵值對(duì)特點(diǎn),也有哈希表的特點(diǎn)
簡(jiǎn)單點(diǎn)說,利用HashMap類:
查找時(shí),給出一個(gè)關(guān)鍵字key,我們可以根據(jù)hash算法計(jì)算出key-value的存儲(chǔ)位置然后取出value
存儲(chǔ)時(shí),我們根據(jù)哈希算法計(jì)算出該鍵值對(duì)應(yīng)該存儲(chǔ)的位置,將其存進(jìn)去。
也就是說,當(dāng)沒有沖突時(shí),HashMap存取的時(shí)間復(fù)雜度為O(1)
這是HashMap類的部分代碼(部分?jǐn)?shù)據(jù)域和構(gòu)造函數(shù))
public class HashMapextends AbstractMap implements Map , Cloneable, Serializable { static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // 默認(rèn)初始容量 static final int MAXIMUM_CAPACITY = 1 << 30; //HashMap的最大容量 static final float DEFAULT_LOAD_FACTOR = 0.75f; //默認(rèn)負(fù)載因子0.75 static final int TREEIFY_THRESHOLD = 8; //當(dāng)某條鏈表中元素的個(gè)數(shù)大于8時(shí)//將轉(zhuǎn)變?yōu)榧t黑樹 transient Node [] table; // table數(shù)組,每一個(gè)元素都是一個(gè)Node對(duì)象,接下來會(huì)介紹Node是什么 transient Set > entrySet; transient int size; //記錄哈希表中的鍵值對(duì)個(gè)數(shù) int threshold; //閾值,即當(dāng)table中元素個(gè)數(shù)大于這個(gè)值就要resize() final float loadFactor; //加載因子
HashMap有四種構(gòu)造函數(shù)
①第一種 允許用戶自己決定初始容量和加載因子,但這個(gè)初始容量不一定是HashMap真正的初始容量,下文會(huì)對(duì)此進(jìn)行解釋
public HashMap(int initialCapacity, float loadFactor) { if (initialCapacity < 0)//初始容量不可以小于0 throw new IllegalArgumentException("Illegal initial capacity: " + initialCapacity); if (initialCapacity > MAXIMUM_CAPACITY) initialCapacity = MAXIMUM_CAPACITY;//不可以大于最大容量 if (loadFactor <= 0 ||Float.isNaN(loadFactor))//加載因子不可以小于0 throw new IllegalArgumentException("Illegal load factor: " + loadFactor); this.loadFactor = loadFactor; this.threshold = tableSizeFor(initialCapacity); }
在構(gòu)造函數(shù)中,我們可以看到,閾值利用tableSizeFor進(jìn)行了計(jì)算,而此時(shí)的閾值并不是真正的閾值,是數(shù)組的容量,我們也會(huì)發(fā)現(xiàn)其實(shí)在構(gòu)造函數(shù)中并沒有給table分配內(nèi)存,這是因?yàn)樵诓迦腈I值對(duì)時(shí),put函數(shù)會(huì)判斷table是否為null,如果是那么用resize()函數(shù)為其分配空間并計(jì)算真正的閾值
其他三種構(gòu)造函數(shù)
public HashMap(int initialCapacity) { this(initialCapacity, DEFAULT_LOAD_FACTOR); } public HashMap() { this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted } public HashMap(Map extends K, ? extends V> m) { this.loadFactor = DEFAULT_LOAD_FACTOR; putMapEntries(m, false); }
}
【小貼士】
1.AbstractMap抽象類是什么?
AbstractMap抽象類實(shí)現(xiàn)了Map接口的大部分方法,讓HashMap繼承它減少了實(shí)現(xiàn)Map接口的工作量。那它為什么是抽象類呢,因?yàn)樗形ㄒ坏囊粋€(gè)抽象方法
Public abstract Set
當(dāng)然在HashMap中有很多方法對(duì)AbstractMap的方法進(jìn)行了覆蓋
下一節(jié):HashMap的數(shù)據(jù)結(jié)構(gòu)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/69987.html
摘要:當(dāng)一個(gè)值中要存儲(chǔ)到的時(shí)候會(huì)根據(jù)的值來計(jì)算出他的,通過哈希來確認(rèn)到數(shù)組的位置,如果發(fā)生哈希碰撞就以鏈表的形式存儲(chǔ)在源碼分析中解釋過,但是這樣如果鏈表過長(zhǎng)來的話,會(huì)把這個(gè)鏈表轉(zhuǎn)換成紅黑樹來存儲(chǔ)。 正文開始 注:JDK版本為1.8 HashMap1.8和1.8之前的源碼差別很大 目錄 簡(jiǎn)介 數(shù)據(jù)結(jié)構(gòu) 類結(jié)構(gòu) 屬性 構(gòu)造方法 增加 刪除 修改 總結(jié) 1.HashMap簡(jiǎn)介 H...
摘要:的工作原理是近年來常見的面試題。讓我們?cè)賮砜纯催@些問題設(shè)計(jì)哪些知識(shí)點(diǎn)的概念中解決碰撞的方法和的應(yīng)用,以及它們?cè)谥械闹匾圆豢勺儗?duì)象的好處多線程的條件競(jìng)爭(zhēng)重新調(diào)整的大小總結(jié)的工作原理基于原理,我們通過和方法儲(chǔ)存和獲取對(duì)象。 HashMap 的工作原理是近年來常見的 Java 面試題。幾乎每個(gè) Java 程序員都知道 HashMap,都知道哪里要用 HashMap,知道Hashtable和...
摘要:根據(jù)的重新計(jì)算值。如果這兩個(gè)的通過比較返回,新添加的將覆蓋集合中原有的,但不會(huì)覆蓋。如果這兩個(gè)的通過比較返回,新添加的將與集合中原有形成鏈,而且新添加的位于鏈的頭部具體說明繼續(xù)看方法的說明。 關(guān)于hashCode hashCode的存在主要是用于查找的快捷性,如Hashtable,HashMap等,hashCode是用來在散列存儲(chǔ)結(jié)構(gòu)中確定對(duì)象的存儲(chǔ)地址的. 1.hashcode是用來...
摘要:為了解決這個(gè)問題設(shè)計(jì)了一個(gè)閾值,其值為容量的,當(dāng)所用容量超過了閾值后,就會(huì)自動(dòng)擴(kuò)充其容量。如果條件競(jìng)爭(zhēng)發(fā)生了,那么就會(huì)產(chǎn)生死循環(huán)了。 由于HashMap的容量是有限的,如果HashMap中的數(shù)組的容量很小,假如只有2個(gè),那么如果要放進(jìn)10個(gè)keys的話,碰撞就會(huì)非常頻繁,此時(shí)一個(gè)O(1)的查找算法,就變成了鏈表遍歷,性能變成了O(n),這是Hash表的缺陷。 為了解決這個(gè)問題,Hash...
摘要:在二叉查找樹強(qiáng)制一般要求以外,對(duì)于任何有效的紅黑樹增加了如下的額外要求節(jié)點(diǎn)是紅色或黑色。紅黑樹有哪些應(yīng)用場(chǎng)景內(nèi)核和系統(tǒng)調(diào)用實(shí)現(xiàn)中使用的完全公平調(diào)度程序使用紅黑樹。 前言 這篇文章是記錄自己分析 Java 8 的 HashMap 源碼時(shí)遇到的疑問和總結(jié),在分析的過程中筆者把遇到的問題都記錄下來,然后逐一擊破,如果有錯(cuò)誤的地方,希望讀者可以指正,筆者感激不盡。 疑問與解答 什么是 initia...
閱讀 610·2021-10-19 11:45
閱讀 1532·2021-09-30 09:48
閱讀 1534·2021-08-16 10:56
閱讀 806·2021-07-26 23:38
閱讀 3259·2019-08-30 13:15
閱讀 2648·2019-08-30 12:45
閱讀 1903·2019-08-29 12:14
閱讀 2218·2019-08-26 18:42