摘要:下面看看的構(gòu)造函數(shù)是如何定義的。的每一個(gè)鍵值對(duì)都是通過(guò)內(nèi)部的靜態(tài)類(lèi)實(shí)例化的。如果你知道內(nèi)部是如何工作的,就非常容易明白內(nèi)部是如何工作的。
LinkedHashSet是HashSet的一個(gè)“擴(kuò)展版本”,HashSet并不管什么順序,不同的是LinkedHashSet會(huì)維護(hù)“插入順序”。HashSet內(nèi)部使用HashMap對(duì)象來(lái)存儲(chǔ)它的元素,而LinkedHashSet內(nèi)部使用LinkedHashMap對(duì)象來(lái)存儲(chǔ)和處理它的元素。這篇文章,我們將會(huì)看到LinkedHashSet內(nèi)部是如何運(yùn)作的及如何維護(hù)插入順序的。
我們首先著眼LinkedHashSet的構(gòu)造函數(shù)。在LinkedHashSet類(lèi)中一共有4個(gè)構(gòu)造函數(shù)。這些構(gòu)造函數(shù)都只是簡(jiǎn)單地調(diào)用父類(lèi)構(gòu)造函數(shù)(如HashSet類(lèi)的構(gòu)造函數(shù))。
下面看看LinkedHashSet的構(gòu)造函數(shù)是如何定義的。
//Constructor - 1 public LinkedHashSet(int initialCapacity, float loadFactor) { super(initialCapacity, loadFactor, true); //Calling super class constructor } //Constructor - 2 public LinkedHashSet(int initialCapacity) { super(initialCapacity, .75f, true); //Calling super class constructor } //Constructor - 3 public LinkedHashSet() { super(16, .75f, true); //Calling super class constructor } //Constructor - 4 public LinkedHashSet(Collection extends E> c) { super(Math.max(2*c.size(), 11), .75f, true); //Calling super class constructor addAll(c); }
在上面的代碼片段中,你可能注意到4個(gè)構(gòu)造函數(shù)調(diào)用的是同一個(gè)父類(lèi)的構(gòu)造函數(shù)。這個(gè)構(gòu)造函數(shù)(父類(lèi)的,譯者注)是一個(gè)包內(nèi)私有構(gòu)造函數(shù)(見(jiàn)下面的代碼,HashSet的構(gòu)造函數(shù)沒(méi)有使用public公開(kāi),譯者注),它只能被LinkedHashSet使用。
這個(gè)構(gòu)造函數(shù)需要初始容量,負(fù)載因子和一個(gè)boolean類(lèi)型的啞值(沒(méi)有什么用處的參數(shù),作為標(biāo)記,譯者注)等參數(shù)。這個(gè)啞參數(shù)只是用來(lái)區(qū)別這個(gè)構(gòu)造函數(shù)與HashSet的其他擁有初始容量和負(fù)載因子參數(shù)的構(gòu)造函數(shù),下面是這個(gè)構(gòu)造函數(shù)的定義,
HashSet(int initialCapacity, float loadFactor, boolean dummy) { map = new LinkedHashMap<>(initialCapacity, loadFactor); }
顯然,這個(gè)構(gòu)造函數(shù)內(nèi)部初始化了一個(gè)LinkedHashMap對(duì)象,這個(gè)對(duì)象恰好被LinkedHashSet用來(lái)存儲(chǔ)它的元素。
LinkedHashSet并沒(méi)有自己的方法,所有的方法都繼承自它的父類(lèi)HashSet,因此,對(duì)LinkedHashSet的所有操作方式就好像對(duì)HashSet操作一樣。
唯一的不同是內(nèi)部使用不同的對(duì)象去存儲(chǔ)元素。在HashSet中,插入的元素是被當(dāng)做HashMap的鍵來(lái)保存的,而在LinkedHashSet中被看作是LinkedHashMap的鍵。
這些鍵對(duì)應(yīng)的值都是常量PRESENT(PRESENT是HashSet的靜態(tài)成員變量,譯者注)。
可以參考How HashSet works internally in Java.
LinkedHashSet使用LinkedHashMap對(duì)象來(lái)存儲(chǔ)它的元素,插入到LinkedHashSet中的元素實(shí)際上是被當(dāng)作LinkedHashMap的鍵保存起來(lái)的。
LinkedHashMap的每一個(gè)鍵值對(duì)都是通過(guò)內(nèi)部的靜態(tài)類(lèi)Entry
before和after來(lái)維護(hù)LinkedHasMap元素的插入順序。這兩個(gè)成員變量分別指向前一個(gè)和后一個(gè)元素,這讓LinkedHashMap也有類(lèi)似雙向鏈表的表現(xiàn)。
private static class Entryextends HashMap.Entry { // These fields comprise the doubly linked list used for iteration. Entry before, after; Entry(int hash, K key, V value, HashMap.Entry next) { super(hash, key, value, next); } }
從上面代碼看到的LinkedHashMap內(nèi)部類(lèi)的前面兩個(gè)成員變量——before和after負(fù)責(zé)維護(hù)LinkedHashSet的插入順序。LinkedHashMap定義的成員變量header保存的是
這個(gè)雙向鏈表的頭節(jié)點(diǎn)。header的定義就像下面這樣,
private transient Entryheader; //Stores the head of the doubly linked list
In LinkedHashMap, the same set of Entry objects (rather references to Entry objects) are arranged in two different manner.
One is the HashMap and another one is Doubly linked list. The Entry objects just sit on heap memory,
unaware of that they are part of two different data structures.
接下來(lái)看一個(gè)例子就知道LinkedHashSet內(nèi)部是如何工作的了。
public class LinkedHashSetExample { public static void main(String[] args) { //Creating LinkedHashSet LinkedHashSetset = new LinkedHashSet (); //Adding elements to LinkedHashSet set.add("BLUE"); set.add("RED"); set.add("GREEN"); set.add("BLACK"); } }
下面的圖片展示了這個(gè)程序是如何運(yùn)行的。
如果你知道LinkedHashMap內(nèi)部是如何工作的,就非常容易明白LinkedHashSet內(nèi)部是如何工作的??匆槐?b>LinkedHashSet和LinkedHashMap的源碼,
你就能夠準(zhǔn)確地理解在Java中LinkedHashSet內(nèi)部是如何工作的。
原文鏈接:How LinkedHashSet Works Internally In Java
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/65565.html
摘要:并把最終的隨機(jī)數(shù)輸出到控制臺(tái)。方法,在集合中如何存儲(chǔ)元素取決于方法的返回值返回,集合中只有一個(gè)元素。創(chuàng)建集合對(duì)象,傳入比較器。 1_HashSet存儲(chǔ)字符串并遍歷 A:Set集合概述及特點(diǎn) 通過(guò)API查看即可 B:案例演示 HashSet存儲(chǔ)字符串并遍歷 import java.util.HashSet; public class Demo1_HashSet { p...
摘要:允許從任一方向來(lái)遍歷對(duì)象,并在遍歷迭代過(guò)程中進(jìn)行修改該對(duì)象,還能獲得迭代器的當(dāng)前位置。這個(gè)構(gòu)造函數(shù)是將返回了一個(gè)對(duì)象給,這也是的存儲(chǔ)實(shí)現(xiàn)原理。 一、容器產(chǎn)生的原因 1.數(shù)組的缺點(diǎn):大小一旦給定就無(wú)法更改,除非復(fù)制到一個(gè)新的數(shù)組中,開(kāi)銷(xiāo)大;而容器類(lèi)都可以自動(dòng)地調(diào)整自己的尺寸。 2.容器功能的多樣性:容器可以實(shí)現(xiàn)各種不同要求,如按不同依據(jù)將元素進(jìn)行排序或者保證容器內(nèi)無(wú)重復(fù)元素等等。關(guān)...
Set接口 Set是一個(gè)不能包含重復(fù)元素的Collection,它模擬了數(shù)學(xué)集抽象,Set接口僅包含從Collection繼承的方法,并添加禁止重復(fù)元素的限制,Set還為equals和hashCode操作的行為添加了一個(gè)更強(qiáng)的契約,允許Set實(shí)例有意義地進(jìn)行比較,即使它們的實(shí)現(xiàn)類(lèi)型不同,如果兩個(gè)Set實(shí)例包含相同的元素,則它們是相等的。 Java平臺(tái)包含三個(gè)通用的Set實(shí)現(xiàn):HashSet、Tre...
摘要:當(dāng)復(fù)制集合中的所有元素來(lái)創(chuàng)建新的集合時(shí),要求集合中的所有元素必須是同一個(gè)枚舉類(lèi)的枚舉值各實(shí)現(xiàn)類(lèi)的性能分析的性能總比好,特別是最常用的添加查詢(xún)?cè)氐炔僮鳌R驗(yàn)樾枰~外的紅黑樹(shù)算法來(lái)維護(hù)集合元素的次序。在創(chuàng)建時(shí)進(jìn)行,以防對(duì)集合的意外非同步訪(fǎng)問(wèn) HashSet 大多時(shí)候使用Set集合時(shí)就是使用HashSet實(shí)現(xiàn)類(lèi)。HashSet按Hash算法來(lái)存儲(chǔ)集合中的元素,因此具有很好的存取和查找性能 ...
摘要:就有這個(gè)功能,它是怎么實(shí)現(xiàn)有序的呢源碼分析繼承自,讓我們直接上源碼來(lái)看看它們有什么不同。是有序的,它是按照插入的順序排序的。所以,是不支持按訪(fǎng)問(wèn)順序?qū)υ嘏判虻?,只能按插入順序排序? 介紹 上一節(jié)我們說(shuō)HashSet中的元素是無(wú)序的,那么有沒(méi)有什么辦法保證Set中的元素是有序的呢? 答案是當(dāng)然可以。 LinkedHashSet就有這個(gè)功能,它是怎么實(shí)現(xiàn)有序的呢? 源碼分析 Linked...
閱讀 3154·2021-11-22 14:45
閱讀 3300·2019-08-29 13:11
閱讀 2306·2019-08-29 12:31
閱讀 922·2019-08-29 11:21
閱讀 2991·2019-08-29 11:09
閱讀 3617·2019-08-28 18:11
閱讀 1420·2019-08-26 13:58
閱讀 1273·2019-08-26 13:27