摘要:到此發(fā)現(xiàn),實(shí)際上可以拆分成跟指的是,則是指實(shí)現(xiàn)了接口,這樣看來,的實(shí)現(xiàn)其實(shí)就比較簡單了,下面開始分析源碼。
概述
在分析HashSet源碼前,先看看HashSet的繼承關(guān)系
HashSet繼承關(guān)系
從上圖可以看出,HashSet繼承自AbstractSet,實(shí)現(xiàn)了Set接口,接著看一下源碼中的注釋
This class implements the Set interface, backed by a hash table
(actually a HashMapinstance). It makes no guarantees as to the
iteration order of the set; in particular, it does not guarantee that the
order will remain constant over time. This class permits the null element.
HashSet實(shí)現(xiàn)了Set接口,內(nèi)部有一個哈希表支撐(實(shí)際上就是一個HashMap實(shí)例),它不保證迭代的順序;尤其是,隨著時間的變化,它不能保證set的迭代順序保持不變。允許插入空值。
到此發(fā)現(xiàn),HashSet實(shí)際上可以拆分成Hash跟Set,Hash指的是HashMap,Set則是指實(shí)現(xiàn)了Set接口,這樣看來,HashSet的實(shí)現(xiàn)其實(shí)就比較簡單了,下面開始分析源碼。
正文
成員變量
//序列化ID static final long serialVersionUID = -5024744406713321676L; //內(nèi)置的HashMap private transient HashMapmap; // 就是一個傀儡,填充HashMap的Value而已,沒有實(shí)際意義 private static final Object PRESENT = new Object();
構(gòu)造方法
空的構(gòu)造方法
初始化一個空的HashMap
public HashSet() { map = new HashMap<>(); }
帶有容量的構(gòu)造方法
HashMap給定一個容量
public HashSet(int initialCapacity) { map = new HashMap<>(initialCapacity); }
帶有容量跟負(fù)載因子的構(gòu)造方法
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<>(initialCapacity, loadFactor); }
帶有容量跟負(fù)載因子,以及Value類型區(qū)分
dummy作為Value是基本類型跟引用類型,注意此處初始化的是一個LinkedHashMap
HashSet(int initialCapacity, float loadFactor, boolean dummy) { map = new LinkedHashMap<>(initialCapacity, loadFactor); }
通過一個集合初始化
public HashSet(Collection extends E> c) { map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16)); addAll(c); }
調(diào)用addAll方法
public boolean addAll(Collection extends E> c) { boolean modified = false; //循環(huán)遍歷 for (E e : c) //如果set中沒有此元素,添加成功 if (add(e)) modified = true; return modified; }
增加元素
添加一個元素,如果Map中存在,返回false,否則返回true
public boolean add(E e) { return map.put(e, PRESENT)==null; }
看一下Map的put方法
public V put(K key, V value) { if (table == EMPTY_TABLE) { inflateTable(threshold); } if (key == null) return putForNullKey(value); int hash = sun.misc.Hashing.singleWordWangJenkinsHash(key); int i = indexFor(hash, table.length); for (HashMapEntrye = table[i]; e != null; e = e.next) { Object k; //這里比較了hash值跟equals方法 if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; addEntry(hash, key, value, i); return null; }
所以Set元素必須復(fù)寫hashcode跟equals方法,不然會導(dǎo)致元素錯亂
刪除元素
public boolean remove(Object o) { //直接調(diào)用map的方法 return map.remove(o)==PRESENT; }
clear
public void clear() {
//調(diào)用map的Clear方法
map.clear(); }
contains方法
public boolean contains(Object o) { 調(diào)用map的contains方法 return map.containsKey(o); }
isEmpty
public boolean isEmpty() { //調(diào)用map的isEmpty方法 return map.isEmpty(); }
迭代
public Iterator
//因?yàn)椴恍枰獀alue,所以只是調(diào)用了keySet的iterator
return map.keySet().iterator(); }
分析了一下,其實(shí)最終的底層實(shí)現(xiàn)都是在調(diào)用HashMap的方法,所以了解了HashMap的源碼之后,HashSet其實(shí)就會比較簡單了
總結(jié)
HashSet是非線程安全的,允許插入空元素
HashSet不允許重復(fù)元素
HashSet的Key需要復(fù)寫hashcode跟equals方法
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/67728.html
摘要:源碼分析屬性內(nèi)部使用虛擬對象,用來作為放到中構(gòu)造方法非,主要是給使用的構(gòu)造方法都是調(diào)用對應(yīng)的構(gòu)造方法。遍歷元素直接調(diào)用的的迭代器。什么是機(jī)制是集合中的一種錯誤機(jī)制。當(dāng)使用迭代器迭代時,如果發(fā)現(xiàn)集合有修改,則快速失敗做出響應(yīng),拋出異常。 簡介 集合,這個概念有點(diǎn)模糊。 廣義上來講,java中的集合是指java.util包下面的容器類,包括和Collection及Map相關(guān)的所有類。 中...
摘要:本文是作者自己對中線程的狀態(tài)線程間協(xié)作相關(guān)使用的理解與總結(jié),不對之處,望指出,共勉。當(dāng)中的的數(shù)目而不是已占用的位置數(shù)大于集合番一文通版集合番一文通版垃圾回收機(jī)制講得很透徹,深入淺出。 一小時搞明白自定義注解 Annotation(注解)就是 Java 提供了一種元程序中的元素關(guān)聯(lián)任何信息和著任何元數(shù)據(jù)(metadata)的途徑和方法。Annotion(注解) 是一個接口,程序可以通過...
摘要:原文地址游客前言金三銀四,很多同學(xué)心里大概都準(zhǔn)備著年后找工作或者跳槽。最近有很多同學(xué)都在交流群里求大廠面試題。 最近整理了一波面試題,包括安卓JAVA方面的,目前大廠還是以安卓源碼,算法,以及數(shù)據(jù)結(jié)構(gòu)為主,有一些中小型公司也會問到混合開發(fā)的知識,至于我為什么傾向于混合開發(fā),我的一句話就是走上編程之路,將來你要學(xué)不僅僅是這些,豐富自己方能與世接軌,做好全棧的裝備。 原文地址:游客kutd...
摘要:三系列用于保存鍵值對,無論是,還是已棄用的或者線程安全的等,都是基于紅黑樹。是完全基于紅黑樹的,并在此基礎(chǔ)上實(shí)現(xiàn)了接口。可以看到,只有紅黑樹,且紅黑樹是通過內(nèi)部類來實(shí)現(xiàn)的。 JDK容器 前言 閱讀JDK源碼有段時間了,準(zhǔn)備以博客的形式記錄下來,也方便復(fù)習(xí)時查閱,本文參考JDK1.8源碼。 一、Collection Collection是所有容器的基類,定義了一些基礎(chǔ)方法。List、Se...
閱讀 1204·2021-11-15 18:00
閱讀 1798·2021-10-08 10:15
閱讀 763·2021-09-04 16:48
閱讀 2388·2021-09-04 16:48
閱讀 1321·2019-08-29 18:40
閱讀 976·2019-08-29 13:08
閱讀 2997·2019-08-26 14:06
閱讀 1119·2019-08-26 13:35