日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

Java的Set集合,你真的會用嗎?HashSet/TreeSet/LinkedHashSet

來源: 責編: 時間:2023-12-01 17:13:52 258觀看
導讀引言當我們需要對元素去重的時候,會使用Set集合,可選的Set集合有三個,分別是HashSet、LinkedHashSet、TreeSet,這三個常用的Set集合有什么區別呢?底層實現原理是什么樣?這篇文章一起來深度剖析。共同點這三個類都實現了Set

引言

當我們需要對元素去重的時候,會使用Set集合,可選的Set集合有三個,分別是HashSet、LinkedHashSet、TreeSet,這三個常用的Set集合有什么區別呢?底層實現原理是什么樣?這篇文章一起來深度剖析。8AN28資訊網——每日最新資訊28at.com

共同點這三個類都實現了Set接口,所以使用方式都是一樣的,使用add()方法添加元素,使用remove()刪除元素,使用contains()方法判斷元素是否存在,使用iterator()方法迭代遍歷元素,這三個類都可以去除重復元素。8AN28資訊網——每日最新資訊28at.com

特性8AN28資訊網——每日最新資訊28at.com

  1. HashSet是最基礎的Set集合,可以去除重復元素,元素存儲是無序的。
  2. LinkedHashSet在HashSet功能基礎上,增加了按照元素插入順序或者訪問順序的迭代方式。
  3. TreeSet在HashSet功能基礎上,可以保證按照元素大小順序排列。

底層實現8AN28資訊網——每日最新資訊28at.com

  1. HashSet是基于HashMap實現的,使用組合的方式,并非繼承。
  2. LinkedHashSet繼承自HashSet,而內部則是采用組合LinkedHashMap的方式實現的。[流汗] 就是這么亂,一會兒看一下源碼就明白了。
  3. TreeSet是基于TreeMap實現的,采用組合的方式,跟上面兩個Set集合沒關系。

圖片圖片8AN28資訊網——每日最新資訊28at.com

下面詳細看一下這三個Set集合源碼的底層實現:8AN28資訊網——每日最新資訊28at.com

HashSet源碼實現

類屬性

public class HashSet<E>        extends AbstractSet<E>        implements Set<E>, Cloneable, java.io.Serializable {    /**     * 使用HashMap存儲數據     */    private transient HashMap<E, Object> map;    /**     * value的默認值     */    private static final Object PRESENT = new Object();}

可以看出HashSet實現了Set接口,內部采用HashMap存儲元素,利用了HashMap的key不能重復的特性,實現元素去重。而value使用默認值,是一個空對象,沒有任何作用,純粹占坑。8AN28資訊網——每日最新資訊28at.com

初始化

HashSet常用的構造方法有兩個,有參構造方法,可以指定初始容量和負載系數。8AN28資訊網——每日最新資訊28at.com

/** * 無參構造方法 */HashSet<Integer> hashSet1 = new HashSet<>();/** * 有參構造方法,指定初始容量和負載系數 */HashSet<Integer> hashSet = new HashSet<>(16, 0.75f);

再看一下構造方式對應的源碼實現:8AN28資訊網——每日最新資訊28at.com

/** * 無參構造方法 */public HashSet() {    map = new HashMap<>();}/** * 有參構造方法,指定初始容量和負載系數 */public HashSet(int initialCapacity, float loadFactor) {    map = new HashMap<>(initialCapacity, loadFactor);}

HashSet的構造方式源碼也很簡單,都是利用的HashMap的構造方法實現。8AN28資訊網——每日最新資訊28at.com

常用方法源碼

再看一下HashSet常用方法源碼實現:8AN28資訊網——每日最新資訊28at.com

/** * 添加元素 */public boolean add(E e) {    return map.put(e, PRESENT) == null;}/** * 刪除元素 */public boolean remove(Object o) {    return map.remove(o) == PRESENT;}/** * 判斷是否包含元素 */public boolean contains(Object o) {    return map.containsKey(o);}/** * 迭代器 */public Iterator<E> iterator() {    return map.keySet().iterator();}

HashSet方法源碼也很簡單,都是利用HashMap的方法實現邏輯。利用HashMap的key不能重復的特性,value使用默認值,contains()方法和iterator()方法也都是針對key進行操作。8AN28資訊網——每日最新資訊28at.com

LinkedHashSet源碼實現

類屬性

LinkedHashSet繼承自HashSet,沒有任何私有的屬性。8AN28資訊網——每日最新資訊28at.com

public class LinkedHashSet<E>        extends HashSet<E>        implements Set<E>, Cloneable, java.io.Serializable {}

初始化

LinkedHashSet常用的構造方法有三個,有參構造方法,可以指定初始容量和負載系數。8AN28資訊網——每日最新資訊28at.com

/** * 無參構造方法 */Set<Integer> linkedHashSet1 = new LinkedHashSet<>();/** * 有參構造方法,指定初始容量 */Set<Integer> linkedHashSet2 = new LinkedHashSet<>(16);/** * 有參構造方法,指定初始容量和負載系數 */Set<Integer> linkedHashSet3 = new LinkedHashSet<>(16, 0.75f);

再看一下構造方法的源碼實現:8AN28資訊網——每日最新資訊28at.com

/** * 無參構造方法 */public LinkedHashSet() {    super(16, .75f, true);}/** * 有參構造方法,指定初始容量 */public LinkedHashSet() {    super(16, .75f, true);}/** * 有參構造方法,指定初始容量和負載系數 */public LinkedHashSet(int initialCapacity, float loadFactor) {    super(initialCapacity, loadFactor, true);}

LinkedHashSet的構造方法使用的是父類HashSet的構造方法,而HashSet的構造方法使用的是LinkedHashMap的構造方法,設計的就是這么亂!8AN28資訊網——每日最新資訊28at.com

public class HashSet<E>        extends AbstractSet<E>        implements Set<E>, Cloneable, java.io.Serializable {    /**     * HashSet的構造方法,底層使用的是LinkedHashMap,專門給LinkedHashSet使用     *     * @param initialCapacity 初始容量     * @param loadFactor      負載系數     * @param dummy           這個字段沒啥用     */    HashSet(int initialCapacity, float loadFactor, boolean dummy) {        map = new LinkedHashMap<>(initialCapacity, loadFactor);    }}

LinkedHashSet的其他方法也是使直接用的父類HashSet的方法,就不用看了。8AN28資訊網——每日最新資訊28at.com

LinkedHashSet額外實現了按照元素的插入順序或者訪問順序進行迭代的功能,是使用LinkedHashMap的實現,不了解LinkedHashMap的,可以看一下上篇文章對LinkedHashMap的源碼解析。8AN28資訊網——每日最新資訊28at.com

TreeSet源碼實現

類屬性

public class TreeSet<E> extends AbstractSet<E>        implements NavigableSet<E>, Cloneable, java.io.Serializable {    /**     * 用來存儲數據     */    private transient NavigableMap<E, Object> m;    /**     * value的默認值     */    private static final Object PRESENT = new Object();}

TreeSet內部使用NavigableMap存儲數據,而NavigableMap是TreeMap的父類,后面在初始化NavigableMap的時候,會用TreeMap進行替換。而value使用默認空對象,與HashSet類似。8AN28資訊網——每日最新資訊28at.com

初始化

TreeSet有兩個構造方法,有參構造方法,可以指定排序方式,默認是升序。8AN28資訊網——每日最新資訊28at.com

/** * 無參構造方法 */TreeSet<Integer> treeSet1 = new TreeSet<>();/** * 有參構造方法,傳入排序方式,默認升序,這里傳入倒序 */TreeSet<Integer> treeSet2 = new TreeSet<>(Collections.reverseOrder());

再看一下構造方法的源碼實現:8AN28資訊網——每日最新資訊28at.com

TreeSet(NavigableMap<E,Object> m) {    this.m = m;}/** * 無參構造方法 */public TreeSet() {    this(new TreeMap<E, Object>());}/** * 有參構造方法,傳入排序方式,默認升序,這里傳入倒序 */public TreeSet(Comparator<? super E> comparator) {    this(new TreeMap<>(comparator));}

TreeSet的構造方法內部是直接使用的TreeMap的構造方法,是基于TreeMap實現的。8AN28資訊網——每日最新資訊28at.com

常用方法源碼

/** * 添加元素 */public boolean add(E e) {    return m.put(e, PRESENT) == null;}/** * 刪除元素 */public boolean remove(Object o) {    return m.remove(o) == PRESENT;}/** * 判斷是否包含元素 */public boolean contains(Object o) {    return m.containsKey(o);}/** * 迭代器 */public Iterator<E> iterator() {    return m.navigableKeySet().iterator();}

TreeSet常用方法的底層實現都是使用的TreeMap的方法邏輯,就是這么偷懶。8AN28資訊網——每日最新資訊28at.com

TreeSet可以按元素大小順序排列的功能,也是使用TreeMap實現的,感興趣的可以看一下上篇文章講的TreeMap源碼。由于TreeSet可以元素大小排列,所以跟其他Set集合相比,增加了一些按照元素大小范圍查詢的方法。8AN28資訊網——每日最新資訊28at.com

其他方法列表:8AN28資訊網——每日最新資訊28at.com

作用
8AN28資訊網——每日最新資訊28at.com

方法簽名
8AN28資訊網——每日最新資訊28at.com

獲取第一個元素
8AN28資訊網——每日最新資訊28at.com

E first()
8AN28資訊網——每日最新資訊28at.com

獲取最后一個元素
8AN28資訊網——每日最新資訊28at.com

E last()
8AN28資訊網——每日最新資訊28at.com

獲取大于指定鍵的最小鍵
8AN28資訊網——每日最新資訊28at.com

E higher(E e)
8AN28資訊網——每日最新資訊28at.com

獲取小于指定鍵的最大元素
8AN28資訊網——每日最新資訊28at.com

E lower(E e)
8AN28資訊網——每日最新資訊28at.com

獲取大于等于指定鍵的最小鍵
8AN28資訊網——每日最新資訊28at.com

E ceiling(E e)
8AN28資訊網——每日最新資訊28at.com

獲取小于等于指定鍵的最大鍵
8AN28資訊網——每日最新資訊28at.com

E floor(E e)
8AN28資訊網——每日最新資訊28at.com

獲取并刪除第一個元素
8AN28資訊網——每日最新資訊28at.com

E pollFirst()
8AN28資訊網——每日最新資訊28at.com

獲取并刪除最后一個元素
8AN28資訊網——每日最新資訊28at.com

E pollLast()
8AN28資訊網——每日最新資訊28at.com

獲取前幾個元素(inclusive表示是否包含當前元素)
8AN28資訊網——每日最新資訊28at.com

NavigableSetheadSet(E toElement, boolean inclusive)
8AN28資訊網——每日最新資訊28at.com

獲取后幾個元素(inclusive表示是否包含當前元素)
8AN28資訊網——每日最新資訊28at.com

NavigableSettailSet(E fromElement, boolean inclusive)
8AN28資訊網——每日最新資訊28at.com

獲取其中一段元素集合(inclusive表示是否包含當前元素)
8AN28資訊網——每日最新資訊28at.com

NavigableSetsubSet(E fromElement, boolean fromInclusive, E toElement,   boolean toInclusive)
8AN28資訊網——每日最新資訊28at.com

獲取其中一段元素集合(左開右開)
8AN28資訊網——每日最新資訊28at.com

SortedSetsubSet(E fromElement, E toElement)
8AN28資訊網——每日最新資訊28at.com

獲取前幾個元素(不包含當前元素)
8AN28資訊網——每日最新資訊28at.com

SortedSetheadSet(E toElement)
8AN28資訊網——每日最新資訊28at.com

獲取后幾個元素(不包含當前元素)
8AN28資訊網——每日最新資訊28at.com

SortedSettailSet(E fromElement)
8AN28資訊網——每日最新資訊28at.com

總結

HashSet、LinkedHashSet、TreeSet,這三個常用的Set集合的共同點是都實現了Set接口,所以使用方式都是一樣的,使用add()方法添加元素,使用remove()刪除元素,使用contains()方法判斷元素是否存在,使用iterator()方法迭代遍歷元素,這三個類都可以去除重復元素。8AN28資訊網——每日最新資訊28at.com

不同點是:HashSet的關鍵特性:8AN28資訊網——每日最新資訊28at.com

  1. 是最基礎的Set集合,可以去除重復元素。
  2. HashSet是基于HashMap實現的,使用組合的方式,并非繼承。
  3. 利用了HashMap的key不重復的特性,而value是一個默認空對象,其他方法也都是使用HashMap實現。

LinkedHashSet的關鍵特性:8AN28資訊網——每日最新資訊28at.com

  1. LinkedHashSet繼承自HashSet,而內部則是采用組合LinkedHashMap的方式實現的。
  2. LinkedHashSet在HashSet功能基礎上,增加了按照元素插入順序或者訪問順序的迭代方式,代價是額外增加一倍的存儲空間。
  3. 方法內部都是使用LinkedHashMap實現的。

TreeSet的關鍵特性:8AN28資訊網——每日最新資訊28at.com

  1. TreeSet是基于TreeMap實現的,也是采用組合的方式。
  2. TreeSet在HashSet功能基礎上,可以保證按照元素大小順序排列,代價是查詢、插入、刪除接口的時間復雜度從O(1)退化到O(log n)。
  3. 方法內部都是使用TreeMap實現的。

本文鏈接:http://www.www897cc.com/showinfo-26-35869-0.htmlJava的Set集合,你真的會用嗎?HashSet/TreeSet/LinkedHashSet

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: C 語言中 const 和 static 的深入解析

下一篇: 構建實時推薦系統:利用MongoDB和機器學習算法

標簽:
  • 熱門焦點
Top 主站蜘蛛池模板: 焉耆| 恩施市| 汕头市| 名山县| 竹山县| 临潭县| 奇台县| 九寨沟县| 兴国县| 贡嘎县| 瑞金市| 龙陵县| 芦溪县| 栾城县| 黔东| 武乡县| 南溪县| 全州县| 甘德县| 洛隆县| 道孚县| 巴塘县| 祁连县| 灵宝市| 教育| 大理市| 韶山市| 辛集市| 景德镇市| 浦县| 定陶县| 农安县| 漾濞| 达拉特旗| 西峡县| 新密市| 松桃| 措美县| 二连浩特市| 镇原县| 裕民县|