hashmap實現了什么接口?
Map表示映射,接口指定了一組由鍵值對組織的集合。鍵必須是唯一的,并且映射中的數據可以t被排序,即地圖中數據的順序與數據放置的順序無關。,它的基本操作是get和put,也就是put數據和fetch數據,我們通常通過按鍵得到它對應的valu
linkdHashSet底層怎么實現元素有序?
從源代碼角度追根究底linkedHashSet!
首先看看linkedHashSet類中的所有方法,發現都只是一些構造方法,沒什么特別的。。spliterator方法只是一個迭代器!
從構造函數中的超級方法點可以看出,構造函數中的父構造函數使用了linkedHashMap進行實例化,因此linkedHashSet的特性必然與linkedHashMap密切相關,換句話說,linkedHashSet的輸出順序來自于linkedHashMap
以下是對linkedHashMap的詳細分析:
linkedHashMap繼承HashMap并實現Map。顯然linkedHashMap也被認為是HashMap,保留了數組鏈表的結構。至于順序的原因,肯定不會是因為Map接口和繼承HashMap,也就是說linkedHashMap的順序肯定是在linkedHashMap類中實現的。
Hashmap的底層數據結構是將數組中的位置作為桶,在每個桶中放一個鏈表(或者紅黑樹)。但是,hashCode落入的桶是不確定的,沒有相關性,所以HashMap可以t以有序的輸出,而linkedHashMap使用的是雙鏈表形式。存儲在Map中的數據不僅使用鏈表來維護每個桶中的順序,還維護每個值中的順序。
借個圖,如下:
而且linkedHashMap有兩種迭代,一種是按插入順序排序(迭代時像隊列),另一種是按訪問排序(像棧一樣,最后一次訪問放在棧頭,可以實現為LRU)。
下面分析主要的源代碼:
1、先看linkedHashMap中的內部類條目:
Entry繼承自一個鍵值結構,比如Node對象中的hash、key和值,next用作hashMap中的同一個bucket。表面的條目指向,linkedHashMap.entry新獲取這些屬性,并定義了兩個新的屬性,Entrybefore,after,用來維護所有條目的一個點,成為一個雙向鏈表。
其余的內部類,如linkedKeyIterator和linkedEntrySet,用作迭代器。
2、看linkedHashMap中的屬性:
linkedHashMap中的主要屬性有三個heads,tail(維護鏈表的頭尾,很好理解),注釋accessOrder寫的很清楚,即訪問順序為真,插入順序為假;
3,linkedHashMap中的方法:①,put方法:我繞過linkedHashMap,沒有找不到put方法。是用的HashMap的put方法嗎?那條目鏈表是怎么做的呢?
從HashMap中的put方法可以看出,計算完哈希值后調用putVal方法,生成新插入的元素時使用newNode方法。linkedHashMap不重寫put方法,但重寫newNode方法。從代碼中,我們可以看到HashMap中的newNode方法。只是簡單的new返回一個節點,linkedHashMap中的newNode方法不僅添加了對象,還調用了linkNodeLast將對象掛在鏈表的尾節點上形成鏈表。(順便可以看出jdk中的數據結構將多態特性(重寫后調用子類方法)運用的淋漓盡致)
和newNode方法類似的還有一個newTreeNode方法,也是在HashMap中的put方法中調用的,也就是紅黑樹結構;
(2)、獲取方法:
從get方法可以看出,如果accessOrder為false,那么linkedHashMap使用的get方法與HashMap相同,計算對應的哈希值,比較鍵值(,等于),如果匹配則返回。如果accessOrder為真,則調用afterNodeAccess方法判斷各種情況,然后將這個值設置為tail,保證是棧頭的位置,下次會先找到。代碼截圖如上!
(3)、拆卸方法:
linkedHashMap中的remove方法和HashMap中的一樣,只是HashMap中最后一個afterNodeRemoval方法的方法體是空的,而在l。InkedHashMap被重寫,這個節點的最后一個節點連接到前一個節點,相當于解耦。。代碼如下:
一般來說,linkedHashMap相比HashMap增加了鏈表特性,保持了元素的順序。雖然大多數方法使用HashMap方法,但是在linkedHashMap中重寫的多態特性是以不同的實現的。可以說這是我們在開發代碼時應該學習的,以后可以通過重寫一些方法來擴展其他類型的HashMap!
linkedHashMap說到這里,作者已經分享了很多java技術,其中很多都幫助了一些朋友!會繼續分享,敬請關注。。。