亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java中HashSet和LinkedHashSet詳解

 更新時間:2023年09月04日 09:12:45   作者:給你兩窩窩  
這篇文章主要介紹了Java中HashSet和LinkedHashSet詳解,   HashSet是Set接口的子類,其內(nèi)部采用了HashMap作為數(shù)據(jù)存儲,HashSet其實(shí)就是在操作HashMap的key,HashSet是無序存儲的,不能保證元素的順序;HashSet并沒有進(jìn)行同步處理,因此是線程不安全的,需要的朋友可以參考下

一、HashSet介紹

HashSet是Set接口的子類,其內(nèi)部采用了HashMap作為數(shù)據(jù)存儲,HashSet其實(shí)就是在操作HashMap的key。

  • HashSet是無序存儲的,不能保證元素的順序;
  • HashSet并沒有進(jìn)行同步處理,因此是線程不安全的;
  • HashSet可以存儲null元素,但只能存儲一個。

二、源碼解析

1、HashSet實(shí)現(xiàn)的接口

如下圖:

觀察上圖:

  • AbstractSet類:該類提供了Set接口的骨架實(shí)現(xiàn),通過擴(kuò)展此類來實(shí)現(xiàn)集合的過程與通過擴(kuò)展AbstractCollection實(shí)現(xiàn)集合的過程相同,除了此類的子類中的所有方法和構(gòu)造函數(shù)都必須遵守由Set接口施加的附加約束(例如,添加方法不能允許將一個對象的多個實(shí)例添加到集合中)。
  • Set接口:繼承Collection接口,添加了所有構(gòu)造函數(shù)的約定以及add,equals和hashCode方法的約定
  • Serializable接口:主要用于序列化,即:能夠?qū)ο髮懭氪疟P。與之對應(yīng)的還有反序列化操作,就是將對象從磁盤中讀取出來。因此如果要進(jìn)行序列化和反序列化,ArrayList的實(shí)例對象就必須實(shí)現(xiàn)這個接口,否則在實(shí)例化的時候程序會報錯(java.io.NotSerializableException)。
  • Cloneable接口:實(shí)現(xiàn)Cloneable接口的類能夠調(diào)用clone方法,如果沒有實(shí)現(xiàn)Cloneable接口就調(diào)用方法,就會拋出異常(java.lang.CloneNotSupportedException)。

2、HashSet中的變量

序列化ID

static final long serialVersionUID = -5024744406713321676L

底層使用HashMap來保存所有元素,確切說存儲在map的key中,并使用transient關(guān)鍵字修飾,防止被序列化

private transient HashMap<E,Object> map

常量,構(gòu)造一個虛擬的對象PRESENT,默認(rèn)為map的value值(HashSet中只需要用到鍵,而HashMap是key-value鍵值對,使用PRESENT作為value的默認(rèn)填充值,解決差異問題)

private static final Object PRESENT = new Object()

3、HashSet的構(gòu)造方法

(1)無參構(gòu)造

    public HashSet() {
        map = new HashMap<>();
    }

總結(jié):默認(rèn)的無參構(gòu)造,其底層會初始化一個空的HashMap,并使用默認(rèn)初始容量16和負(fù)載因子0.75。

(2)帶集合參數(shù)的構(gòu)造方法

    public HashSet(Collection<? extends E> c) {
        map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
        addAll(c);
    }

總結(jié):帶集合參數(shù)的構(gòu)造方法,底層使用默認(rèn)的負(fù)載因子0.75和足以包含指定集合中所有怨怒是的初始容量來構(gòu)造一個HashMap。

(3)帶初始容量的構(gòu)造方法

    public HashSet(int initialCapacity) {
        map = new HashMap<>(initialCapacity);
    }

總結(jié):以指定初始容量的HashMap構(gòu)造一個HashSet。

(4) 帶初始容量和負(fù)載因子的構(gòu)造方法

    public HashSet(int initialCapacity, float loadFactor) {
        map = new HashMap<>(initialCapacity, loadFactor);
    }

總結(jié):構(gòu)造一個具有初始容量和負(fù)載因子的HashMap。

4、常用方法分析

(1)add()方法

add方法底層實(shí)際上是將該元素作為key添加到HashMap中,而PRESENT是作為默認(rèn)的map的value值。

如果添加的元素不存在,則加入到map中,并返回true。如果該元素已經(jīng)存在,則返回false。

map的put方法在添加key-value對時,如果新放入HashMap的Entry中key與集合中原有的Entry的key相同,則新添加的Entry的value會覆蓋原來Entry的value,但是key不會改變。

因此,如果向HashSet中添加一個已經(jīng)存在的元素時,新添加的集合元素不會被放入HashMap中,原有的元素也不會有任何改變,因此Set中的元素也就不會重復(fù)了

    public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }

(2)remove()方法

如果給定的元素在HashSet中,則將其移除,其底層調(diào)用HashMap的remove()方法刪除指定Entry。

    public boolean remove(Object o) {
        return map.remove(o)==PRESENT;
    }

(3) size()方法

返回HashSet中元素的個數(shù)

    public int size() {
        return map.size();
    }

(4)isEmpty()方法

判斷HashSet是否為空

    public boolean isEmpty() {
        return map.isEmpty();
    }

(5)contains()方法

如果HashSet中包含指定元素,則返回true。否則返回false

    public boolean contains(Object o) {
        return map.containsKey(o);
    }

5、HashSet與LinkedHashSet

在HashSet的源碼中有這樣一個構(gòu)造函數(shù):

    HashSet(int initialCapacity, float loadFactor, boolean dummy) {
        map = new LinkedHashMap<>(initialCapacity, loadFactor);
    }

可以看到該構(gòu)造函數(shù)為包訪問權(quán)限,不對外公開。該構(gòu)造函數(shù)以指定的初始容量和負(fù)載因子構(gòu)造一個新的空鏈表哈希集合,其實(shí)它是對LinkedHashSet的支持。

我們可以看看LinkedHashSet的繼承關(guān)系:

因此,在這里我們可以簡單的對LinkedHashSet進(jìn)行分析,它在實(shí)現(xiàn)了Set接口、Cloneable接口和Serializable接口的同時,也繼承了HashSet。

LinkedHashSet的特點(diǎn)如下:

  • LinkedHashSet 是 HashSet 的子類
  • LinkedHashSet 底層是一個 LinkedHashMap,底層維護(hù)了一個數(shù)組+雙向鏈表
  • LinkedHashSet 根據(jù)元素的 hashCode 值來決定元素的存儲位置,同時使用鏈表維護(hù)元素的次序,這使得元素看起來是以插入順序保存的。
  • LinkedHashSet 不允許添重復(fù)元素

來看看LinkedHashSet的構(gòu)造方法

    //使用指定的初始容量和負(fù)載因子構(gòu)造一個新的哈希集合
    public LinkedHashSet(int initialCapacity, float loadFactor) {
        super(initialCapacity, loadFactor, true);
    }
    //使用指定的初始容量和負(fù)載因子構(gòu)造新的哈希集合
    public LinkedHashSet(int initialCapacity) {
        super(initialCapacity, .75f, true);
    }
    //無參構(gòu)造方法,默認(rèn)容量16,負(fù)載因子0.75
    public LinkedHashSet() {
        super(16, .75f, true);
    }
    //基于集合構(gòu)造一個帶有指定元素的非空哈希集合
    public LinkedHashSet(Collection<? extends E> c) {
        super(Math.max(2*c.size(), 11), .75f, true);
        addAll(c);
    }

LinkedHashSet維護(hù)了一個hash表和雙向鏈表,且通過head和tail分別指向鏈表的頭和尾,每一個節(jié)點(diǎn)有before和after屬性,這樣可以形成雙向鏈表。

在添加一個元素時,先求hash值,再求索引,確定該元素在table表中的位置,然后將添加的元素加入到雙向鏈表(如果該元素已經(jīng)存在,則不添加)

三、總結(jié)

1、HashSet總結(jié)

(1)基于HashMap實(shí)現(xiàn)的,默認(rèn)構(gòu)造函數(shù)是構(gòu)建一個初始容量為16,負(fù)載因子為0.75 的HashMap。封裝了一個 HashMap 對象來存儲所有的集合元素,所有放入 HashSet 中的集合元素實(shí)際上由 HashMap 的 key 來保存,而 HashMap 的 value 則存儲了一個 PRESENT,它是一個靜態(tài)的 Object 對象。

(2)當(dāng)我們試圖把某個類的對象當(dāng)成 HashMap的 key,或試圖將這個類的對象放入 HashSet 中保存時,重寫該類的equals(Object obj)方法和 hashCode() 方法很重要,而且這兩個方法的返回值必須保持一致:當(dāng)該類的兩個的 hashCode() 返回值相同時,它們通過 equals() 方法比較也應(yīng)該返回 true。通常來說,所有參與計算 hashCode() 返回值的關(guān)鍵屬性,都應(yīng)該用于作為 equals() 比較的標(biāo)準(zhǔn)。

(3)HashSet的其他操作都是基于HashMap的。

2、LinkedHashSet總結(jié)

LinkedHashSet 底層使用 LinkedHashMap 來保存所有元素,它繼承于 HashSet,其所有的方法操作上又與 HashSet 相同,因此 LinkedHashSet 的實(shí)現(xiàn)上非常簡單,只提供了四個構(gòu)造方法,并通過傳遞一個標(biāo)識參數(shù),調(diào)用父類的構(gòu)造器,底層構(gòu)造一個 LinkedHashMap 來實(shí)現(xiàn),在相關(guān)操作上與父類 HashSet 的操作相同,直接調(diào)用父類 HashSet 的方法即可。

到此這篇關(guān)于Java中HashSet和LinkedHashSet詳解的文章就介紹到這了,更多相關(guān)HashSet和LinkedHashSet內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring?Security登錄表單配置示例詳解

    Spring?Security登錄表單配置示例詳解

    這篇文章主要介紹了Spring?Security登錄表單配置,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-06-06
  • Springboot整合分頁插件PageHelper步驟解析

    Springboot整合分頁插件PageHelper步驟解析

    這篇文章主要介紹了Springboot整合分頁插件PageHelper步驟解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-06-06
  • 關(guān)于Java中的try-with-resources語句

    關(guān)于Java中的try-with-resources語句

    這篇文章主要介紹了關(guān)于Java中的try-with-resources語句,try-with-resources是Java中的環(huán)繞語句之一,旨在減輕開發(fā)人員釋放try塊中使用的資源的義務(wù),需要的朋友可以參考下
    2023-05-05
  • 一文徹底弄懂Java中MultipartFile接口和File類

    一文徹底弄懂Java中MultipartFile接口和File類

    MultipartFile是一個接口,我們可以理解為是Spring?給我們綁定的一個在使用文件上傳等時簡便實(shí)現(xiàn)的口子,這篇文章主要給大家介紹了關(guān)于如何通過一文徹底弄懂Java中MultipartFile接口和File類的相關(guān)資料,需要的朋友可以參考下
    2023-11-11
  • Java基于面向?qū)ο髮?shí)現(xiàn)一個戰(zhàn)士小游戲

    Java基于面向?qū)ο髮?shí)現(xiàn)一個戰(zhàn)士小游戲

    這篇文章主要為大家詳細(xì)介紹了Java如何基于面向?qū)ο髮?shí)現(xiàn)一個戰(zhàn)士小游戲,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以動手嘗試一下
    2022-07-07
  • java 四舍五入保留小數(shù)的實(shí)現(xiàn)方法

    java 四舍五入保留小數(shù)的實(shí)現(xiàn)方法

    下面小編就為大家?guī)硪黄猨ava 四舍五入保留小數(shù)的實(shí)現(xiàn)方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-09-09
  • 一文搞懂Spring中的Bean作用域

    一文搞懂Spring中的Bean作用域

    scope用來聲明容器中的對象所應(yīng)該處的限定場景或者說該對象的存活時間,即容器在對象進(jìn)入其 相應(yīng)的scope之前,生成并裝配這些對象,在該對象不再處于這些scope的限定之后,容器通常會銷毀這些對象,這篇文章主要介紹了Spring中的Bean作用域,需要的朋友可以參考下
    2022-06-06
  • maven項(xiàng)目如何依賴自定jar包

    maven項(xiàng)目如何依賴自定jar包

    這篇文章主要介紹了maven項(xiàng)目如何依賴自定jar包,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-02-02
  • Maven導(dǎo)入依賴時爆紅的幾種解決方法

    Maven導(dǎo)入依賴時爆紅的幾種解決方法

    使用idea建立maven項(xiàng)目,maven導(dǎo)入依賴報紅,本文主要介紹了Maven導(dǎo)入依賴時爆紅的幾種解決方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • Java利用Request請求如何獲取IP地址對應(yīng)的省份、城市詳解

    Java利用Request請求如何獲取IP地址對應(yīng)的省份、城市詳解

    之前已經(jīng)給大家介紹了關(guān)于Java用Request請求獲取IP地址的相關(guān)內(nèi)容,那么下面這篇文章將給大家進(jìn)入深入的介紹,關(guān)于Java利用Request請求如何獲取IP地址對應(yīng)省份、城市的相關(guān)資料,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-10-10

最新評論