摘要:到此發現,實際上可以拆分成跟指的是,則是指實現了接口,這樣看來,的實現其實就比較簡單了,下面開始分析源碼。
概述
在分析HashSet源碼前,先看看HashSet的繼承關系
HashSet繼承關系
從上圖可以看出,HashSet繼承自AbstractSet,實現了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實現了Set接口,內部有一個哈希表支撐(實際上就是一個HashMap實例),它不保證迭代的順序;尤其是,隨著時間的變化,它不能保證set的迭代順序保持不變。允許插入空值。
到此發現,HashSet實際上可以拆分成Hash跟Set,Hash指的是HashMap,Set則是指實現了Set接口,這樣看來,HashSet的實現其實就比較簡單了,下面開始分析源碼。
正文
成員變量
//序列化ID static final long serialVersionUID = -5024744406713321676L; //內置的HashMap private transient HashMapmap; // 就是一個傀儡,填充HashMap的Value而已,沒有實際意義 private static final Object PRESENT = new Object();
構造方法
空的構造方法
初始化一個空的HashMap
public HashSet() { map = new HashMap<>(); }
帶有容量的構造方法
HashMap給定一個容量
public HashSet(int initialCapacity) { map = new HashMap<>(initialCapacity); }
帶有容量跟負載因子的構造方法
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<>(initialCapacity, loadFactor); }
帶有容量跟負載因子,以及Value類型區分
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); }
調用addAll方法
public boolean addAll(Collection extends E> c) { boolean modified = false; //循環遍歷 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元素必須復寫hashcode跟equals方法,不然會導致元素錯亂
刪除元素
public boolean remove(Object o) { //直接調用map的方法 return map.remove(o)==PRESENT; }
clear
public void clear() {
//調用map的Clear方法
map.clear(); }
contains方法
public boolean contains(Object o) { 調用map的contains方法 return map.containsKey(o); }
isEmpty
public boolean isEmpty() { //調用map的isEmpty方法 return map.isEmpty(); }
迭代
public Iterator
//因為不需要value,所以只是調用了keySet的iterator
return map.keySet().iterator(); }
分析了一下,其實最終的底層實現都是在調用HashMap的方法,所以了解了HashMap的源碼之后,HashSet其實就會比較簡單了
總結
HashSet是非線程安全的,允許插入空元素
HashSet不允許重復元素
HashSet的Key需要復寫hashcode跟equals方法
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/67728.html
摘要:源碼分析屬性內部使用虛擬對象,用來作為放到中構造方法非,主要是給使用的構造方法都是調用對應的構造方法。遍歷元素直接調用的的迭代器。什么是機制是集合中的一種錯誤機制。當使用迭代器迭代時,如果發現集合有修改,則快速失敗做出響應,拋出異常。 簡介 集合,這個概念有點模糊。 廣義上來講,java中的集合是指java.util包下面的容器類,包括和Collection及Map相關的所有類。 中...
摘要:本文是作者自己對中線程的狀態線程間協作相關使用的理解與總結,不對之處,望指出,共勉。當中的的數目而不是已占用的位置數大于集合番一文通版集合番一文通版垃圾回收機制講得很透徹,深入淺出。 一小時搞明白自定義注解 Annotation(注解)就是 Java 提供了一種元程序中的元素關聯任何信息和著任何元數據(metadata)的途徑和方法。Annotion(注解) 是一個接口,程序可以通過...
摘要:原文地址游客前言金三銀四,很多同學心里大概都準備著年后找工作或者跳槽。最近有很多同學都在交流群里求大廠面試題。 最近整理了一波面試題,包括安卓JAVA方面的,目前大廠還是以安卓源碼,算法,以及數據結構為主,有一些中小型公司也會問到混合開發的知識,至于我為什么傾向于混合開發,我的一句話就是走上編程之路,將來你要學不僅僅是這些,豐富自己方能與世接軌,做好全棧的裝備。 原文地址:游客kutd...
摘要:三系列用于保存鍵值對,無論是,還是已棄用的或者線程安全的等,都是基于紅黑樹。是完全基于紅黑樹的,并在此基礎上實現了接口。可以看到,只有紅黑樹,且紅黑樹是通過內部類來實現的。 JDK容器 前言 閱讀JDK源碼有段時間了,準備以博客的形式記錄下來,也方便復習時查閱,本文參考JDK1.8源碼。 一、Collection Collection是所有容器的基類,定義了一些基礎方法。List、Se...
閱讀 1192·2021-11-15 18:00
閱讀 1788·2021-10-08 10:15
閱讀 752·2021-09-04 16:48
閱讀 2373·2021-09-04 16:48
閱讀 1313·2019-08-29 18:40
閱讀 964·2019-08-29 13:08
閱讀 2987·2019-08-26 14:06
閱讀 1109·2019-08-26 13:35