1. 程式人生 > >jdk1.8中HashSet與LinkedHashSet原始碼分析

jdk1.8中HashSet與LinkedHashSet原始碼分析

注:基於JDK 1.8.0_131原始碼為例進行分析:

一、HashSet分析

1.1 HashSet的實現

  HashSet實現set介面,是基於HashMap或者LinkedHashMap實現的
  HashSet中封裝了一個 HashMap 物件(也有可能是LinkedHashMap)來儲存所有的集合元素,所有放入 HashSet 中的集合元素實際上由 HashMap 的 key 來儲存,而 HashMap 的 value 則儲存了一個 PRESENT,它是一個靜態的 Object 物件。
  注:LinkedHashMap的實現是繼承自HashMap的,所以一個LinkedHashMap物件可以複製給HashMap引用。
這裡寫圖片描述


說明:

  • 程式碼塊1:HashSet的實現是由HashMap<E,Object>型別的map實現。所以放入hashset集合的元素均存進了map的key中。
  • 程式碼塊2:map中的每一個鍵值對<key,value>的value值均為該靜態Object物件PRESENT。

1.2 HashSet中選擇用HashMap還是LinkedHashMap實現?

這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述
結論:

  • A:前三個建構函式,即訪問許可權為public型別的建構函式均是以HashMap作為實現。而以LinkedHashMap作為實現的建構函式的訪問許可權是預設訪問許可權,即包內訪問許可權。
    即:在java程式設計中,通過new建立的HashSet物件均是以HashMap作為實現基礎
    。只有在jdk中java.util包內的原始碼才可能建立以LinkedHashMap作為實現的HashSet(LinkedHashSet就是通過封裝一個以LinkedHashMap為實現的HashSet來實現的)。
  • B:只有包含三個引數的建構函式才是採用的LinkedHashMap作為實現。

1.3 HashSet的預設大小

這裡寫圖片描述
說明:

  • 程式碼塊1:HashSet中map的預設大小為HashMap的預設值,即容量為16,負載因子為0.75。
  • 程式碼塊2:HashSet中map的容量最小值為16。

1.4 HashSet的add操作實現

這裡寫圖片描述
即直接將鍵值對<e,PRESENT>放入了hashmap中。

1.5 HashSet的contains方法實現

這裡寫圖片描述

1.6 HashSet的迭代

注:只有實現了Iterable介面的類,才能用迭代器進行遍歷。
這裡寫圖片描述
HashSet的中迭代器迭代是基於HashMap的KeySet實現的。

1.7 HashSet的序列化定製

這裡寫圖片描述

1.8 HashSet的用處?

1、 可以在HashSet集合中儲存不重複的元素。如果加入重複元素會自動覆蓋。
2、 HashSet中可以出現一個為null元素。
3、 因為用new建立的HashSet物件中採用HashMap實現時,則不能保證集合中元素的順序,即順序是無序的。

二、LinkedHashSet分析

2.1 LinkedHashSet是通過繼承HashSet進行實現的

這裡寫圖片描述

2.2 LinkedHashSet是通過構造一個具有三個引數的HashSet進行實現的。

這裡寫圖片描述
即:LinkedHashSet是通過繼承HashSet,然後基於LinkedHashMap進行實現的

2.3 HashSet與LinkedHashSet對比總結

  • A:HashSet的public型別建構函式均是採用HashMap實現,所以HashSet能夠儲存不重複的物件,包括NULL。
  • B:LinkedHashSet通過繼承HashSet,採用LinkedhashMap進行實現,所以LinkedHashSet除了具有HashSet的功能外,還能保證元素按照加入順序進行排序。
        LinkedHashSet<Integer> linkedHashSet = new LinkedHashSet<>();
        linkedHashSet.add(11);
        linkedHashSet.add(33);
        linkedHashSet.add(44);
        linkedHashSet.add(22);
        linkedHashSet.add(55);

        System.out.println("LinkedHashSet輸出結果:");
        for (Integer integer : linkedHashSet) {
            System.out.print(integer+" ");
        }
        System.out.println();

        HashSet<Integer> hashSet = new HashSet<>();
        hashSet.add(11);
        hashSet.add(33);
        hashSet.add(44);
        hashSet.add(22);
        hashSet.add(55);

        System.out.println("HashSet輸出結果:");
        for (Integer integer : hashSet) {
            System.out.print(integer+" ");
        }
        System.out.println();

執行結果:

LinkedHashSet輸出結果:
11 33 44 22 55 
HashSet輸出結果:
33 22 55 11 44 

由結果可以看出,LinkedHashSet是按照加入順序進行排序的。

相關推薦

jdk1.8HashSetLinkedHashSet原始碼分析

注:基於JDK 1.8.0_131原始碼為例進行分析: 一、HashSet分析 1.1 HashSet的實現   HashSet實現set介面,是基於HashMap或者LinkedHashMap實現的。   HashSet中封裝了一個 HashM

ConcurrentHashMap JDK1.8結構原理及原始碼分析

注:本文根據網路和部分書籍整理基於JDK1.7書寫,如有雷同敬請諒解  歡迎指正文中的錯誤之處。 資料結構       ConcurrentHashMap 1.8 拋棄了Segment分段鎖機制,採用Node + CAS + Synchronized來保證併發安全進行實現

24、HashSetHashMap原始碼分析

1、HashSet底層是使用HashMap實現的。當使用add方法將物件新增到set當中時,實際上是將該物件作為底層所維護的Map物件的Key,,而value則都是同一個Object物件(該物件我們用不上); HashSet部分原始碼: private transient

為什麼JDK1.8HashSet集合好像是有序的?

我們知道,Set集合是無序集合,即存取順序不一致,但在JDK1.8中存取順序好像是一致的,看下面的例子: 執行結果如下: 在知乎上看到了一篇比較合理的解答,大致是說JDK1.8的中HashS

通俗易懂的JDK1.8HashMap原始碼分析(歡迎探討指正)+ 典型面試題

面試題在最下面 說到HashMap之前,閱讀ArrayList與LinkedList的原始碼後做個總結 ArrayList 底層是陣列,查詢效率高,增刪效率低 LinkedList底層是雙鏈表,查詢效率低,增刪效率高   這裡只是總結看完原始碼後對hashm

jdk1.8hashtable原始碼分析

注:基於JDK 1.8.0_131原始碼為例進行分析 hashtable的結構圖 hashtable採用桶位+連結串列結構實現。 hashtable的實現 採用的是“桶位”,即一個Entry陣列實現: Entry節點的實現:主要

JDK1.8ArrayList的實現原理及原始碼分析

一、概述              ArrayList是Java開發中使用比較頻繁的一個類,通過對原始碼的解讀,可以瞭解ArrayList的內部結構以及實現方法,清楚它的優缺點,以便我們在程式設計時靈活運用。 二、原始碼分析 2.1 類結構  JDK1.8原始碼中的A

JDK1.8TreeMap原始碼解析——紅黑樹刪除

在看本文之前建議先看一下二叉樹的刪除過程,這裡有一篇文章寫得不錯,可以看一下 1、後繼節點 在看原始碼之前,先說說紅黑樹尋找 待刪除節點t 的 後繼節點 的過程: 如果待刪除節點t有右節點,那麼後繼節點為該節點右子樹中最左的節點,也就是右子樹中值最小的節

JDK1.7和1.8HashMapConcurrentHashMap總結比較

談到HashMap和ConcurrentHashMap,必然會聯想到一些其他集合結構,比如HashTable,Vector等,先理一下他們的區別吧。其實HashTable和Vector已經被廢棄了,HashTable和Vector以及ConcurrentHashMap都是執行緒安全的同步結構,區別是

jdk1.8 J.U.C併發原始碼閱讀------AQS之conditionObject內部類分析

一、繼承關係 public class ConditionObject implements Condition, java.io.Serializable 實現了Condition介面和Serializable介面,是AbstractQueuedSynchronize

JDK1.7HashMap死環問題及JDK1.8對HashMap的優化原始碼詳解

一、JDK1.7中HashMap擴容死鎖問題 我們首先來看一下JDK1.7中put方法的原始碼 我們開啟addEntry方法如下,它會判斷陣列當前容量是否已經超過的閾值,例如假設當前的陣列容量是16,載入因子為0.75,即超過了12,並且剛好要插入的索引處有元素,這時候就需要進行擴容操作,可以看到resi

JDK1.8HashMap實現

替換 應該 初始化 第一個元素 擴容 實現 1.8 put 相同 JDK1.8中的HashMap實現跟JDK1.7中的實現有很大差別。下面分析JDK1.8中的實現,主要看put和get方法。 構造方法的時候並沒有初始化,而是在第一次put的時候初始化 put

jdk1.8接口可以寫默認方法

wheel void JD PE 靜態 調用 默認 sta default interface Vehicle {  default void print(){     System.out.println("我是一輛車!");   }   stat

Java7、8HashMap和ConcurrentHashMap原始碼閱讀

首先來看下HashMap的類繼承結構: public class HashMap extends AbstractMap<K,V> impement Map<K,V>,Coloneable,Serializable{ } 可以看出HashMap實現了Map介面。其裡面的方法都是

JSobjectconstructor的分析 面向物件objectconstructor

  面向物件object與constructor    (本文轉自:http://www.cnblogs.com/chengxiangboke/p/9932790.html) 什麼是constructor屬性?它來自哪裡?又將會指向何處?

JSobjectconstructor的分析

引入 prototype 實例化 不難 屬性 png const 出現 tor 什麽是constructor屬性?它來自哪裏?又將會指向何處? 什麽是constructor屬性? constructor是構造函數屬性。 它來自哪裏? 其實constructor屬性是來自 p

5.Java集合框架剖析 之 HashsetLinkedHashSet原始碼剖析

1 package java.util; 2 3 import java.io.InvalidObjectException; 4 import sun.misc.SharedSecrets; 5 6 public class HashSet<E> extends

jdk1.8computeIfAbsent方法用法

computeIfAbsent(K key, Function《? super K, ? extends V> mappingFunction) computeIfAbsent的方法有兩個引數 第一個是所選map的key,第二個是需要做的操作。這個方法當key值不存在

Java——HashSetLinkedHashSet實現刪除重複字元

1.從鍵盤讀取一行字串,去掉重複字元,並打印出來 2.將集合中的重複元素去掉 程式碼如下~ package pra_12; import java.util.ArrayList; import j

1.jdk1.8hashMap的原理,hash衝突如何解決

一:hashMap的工作原理        HashMap是基於鏈地址法的原理,使用put(key, value)儲存物件到HashMap中,使用get(key)從HashMap中獲取物件。        當我們給put()方法傳遞鍵和值時,我們先對鍵呼叫hashCode