哈希表底層深刻


圖片

圖片 1.哈希表的底層結構? Java中的HashSet和HsahMap用的就是哈希表 數據結構決定了數據的檢索,維護的效率。數組的檢索效率高,增刪元素的效率低。而鏈表的增刪元素的效率高,檢索元素的效率低。而哈希表結合了他們的優勢。檢索與增刪效率都高。哈希表的底層結構就是一個數組,數組的長度即哈希表的長度,數組中的每一個空間(也叫桶)存放的是一條鏈表,鏈表中的每一個節點用來存放元素。即一個數組的每一個數組元素是一條鏈表,鏈表的每一個節點存放元素,能夠將數組的每一個元素看作桶,桶裏面能夠有多個元素。桶裏元素直接的數據結構是鏈表。 2.哈希表如何檢索元素? 哈希表首先根據要存放的元素的key獲得hash值,將這個hash值通過"特殊計算的"結果,做爲數組的下標(定位桶),進而肯定將要遍歷的鏈表。就不用遍歷全部的鏈表,因此檢索效率高。 3.哈希表如何增刪元素? 首先一個哈希表的默認初始長度爲16,即數組有16個空間(並不是指能放16個元素)。默認加載因子爲0.75。當向哈希表中添加元素的時候先判斷是否要擴容,若是當前元素的總個數大於16*0.75那麼要進行擴容,新的容量爲原來的2倍。 在向哈希表中添加元素時首先經過要添加的元素的key的hash值,通過特殊算法計算的值做爲下標,肯定這個元素要放到數組中的那個桶裏,而後遍歷這個桶裏的鏈表中的每一個元素,與key進行equals判斷若是equals返回false說明這個元素在哈希表中不存在則插入。若是返回true則不插入。 4.如何計算下標值? 經過要插入的元素的key調用hashcode方法獲得哈希值,並與哈希表的長度減一進行與運算獲得數組下標。 公式:hash(key)&table.length-1 因爲哈希表表長必定是2的指數,即table.length-1的結果的二進制必定所有是1(好比16-1)與hash(key)進行與運算,即hash(key)最高位全爲0,即求hash(key)與表長的餘數,獲得的就是下面的公式。 hash(key)%(table.length)。 這就能夠解釋當表長爲16,元素個數不超過16*0.75時,插入元素就會根據要插入元素的key的的hashcode值與表長取餘獲得下標,這樣在不超過表長的前提下,元素就會散亂的分佈在這16不一樣的桶裏。而決定鏈表的長度主要由加載因子決定。即便hashcode值不一樣但與表長進行取餘,獲得的下標會相同,這樣就會散亂的分佈在16個桶裏 hash() static int hash(int h) { h ^= (h >>> 20) ^ (h >>> 12); return h ^ (h >>> 7) ^ (h >>> 4); } hash值找到對應索引 static int indexFor(int h, int length) { return h & (length-1); } HashMap中則經過h&(length-1)的方法來代替取模,一樣實現了均勻的散列,但效率要高不少,這也是HashMap對Hashtable的一個改進。 length爲2的整數次冪的話,h&(length-1)就至關於對length取模,這樣便保證了散列的均勻,同時也提高了效率。 說明:length爲2的整數次冪的話,爲偶數,這樣length-1爲奇數,奇數的最後一位是1,這樣便保證了h&(length-1)的最後一位可能爲0,也可能爲1(這取決於h的值),即與後的結果可能爲偶數,也可能爲奇數,這樣即可以保證散列的均勻性,而若是length爲奇數的話,很明顯length-1爲偶數,它的最後一位是0,這樣h&(length-1)的最後一位確定爲0,即只能爲偶數,這樣任何hash值都只會被散列到數組的偶數下標位置上,這便浪費了近一半的空間。 5.哈希表中的單鏈表的稀疏程度決定因素? 單鏈表的稀疏程度決定檢索效率高低,而加載因子能夠決定元素的個數,進而決定單鏈表的稀疏程度,哈希初始初始容量越大,加載因子越小,而實際存放的元素越少,單鏈表越稀疏越接近於數組。檢索效率越高,可是越接近於數組,增錢效率就下降了,因此加載因子的大小必定要根據實際需求。 6.hashcode怎麼寫? 由哈希表在插入元素的時候會調用對象的hashcode方法和equals方法,所以重寫十分必要。 原則: 兩個對象的equals返回true,那麼他們的hashcode必定要相等。 兩個對象的hashcode相同,他們的equals不必定返回true。
相關文章
相關標籤/搜索