java 实现set,Java--Set的三个具体实现类
HashSet
HashSet繼承AbstractSet類,實現Set、Cloneable、Serializable接口。其中AbstractSet提供Set接口的骨干實現,從而最大限度地減少了實現此接口所需的工作。Set接口是一種不包括重復元素的Collection。HashSet是無序的,不能保證迭代的次序。可以存儲null值,同時是線程不安全的,底層實現是HashMap。
public class HashSet
extends AbstractSet
implements Set, Cloneable, java.io.Serializable
構造器
/**
* 創建一個空的set,起底層的HashMap的默認初始容量為16,默認的加載因子為0.75
* default initial capacity (16) and load factor (0.75).
*/
public HashSet() {
map = new HashMap<>();
}
/**
* 創建一個包含指定集合中元素的set。
* 其底層的HashMap使用默認負載因子(0.75)和足以容納指定集合中的元素的初始容量創建的
* 其初始容量的計算公式為Math.max((int) (c.size()/.75f) + 1, 16),c即為傳入集合的大小
* @param c the collection whose elements are to be placed into this set
* @throws NullPointerException if the specified collection is null
*/
public HashSet(Collection extends E> c) {
map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
addAll(c);
}
/**
* 創建一個空的set,其底層的HashMap的容量為指定的容量initialCapacity,
* 加載因子為指定的loadFactor
* @param initialCapacity the initial capacity of the hash map
* @param loadFactor the load factor of the hash map
* @throws IllegalArgumentException if the initial capacity is less
* than zero, or if the load factor is nonpositive
*/
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<>(initialCapacity, loadFactor);
}
/**
* 創建一個空的set,其底層的HashMap的容量為指定的容量initialCapacity,
* 加載因子為默認的0.75
* @param initialCapacity the initial capacity of the hash table
* @throws IllegalArgumentException if the initial capacity is less
* than zero
*/
public HashSet(int initialCapacity) {
map = new HashMap<>(initialCapacity);
}
容量 * 加載因子=threshold,為這個容器的臨界值,當存儲的元素到了這個臨界值,那么容器就會自動擴容。
方法
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
?該方法的作用是:如果指定的元素尚不存在,則將其添加到該集合中。可以看到add方法的底層實現是將指定的元素存入到聲明的HashMap中,將元素值作為map的key,然后指定一個PRESENT作為value。
?這個value值是一個常量,所有添加到set中的元素,最終添加到對應的hashmap中的時候,對應的value都是PRESENT:
private static final Object PRESENT = new Object();
?添加到set的元素實際存儲到了map的key中,這也能夠保證存入到set中的元素不會重復。
public Iterator iterator() {
return map.keySet().iterator();
}
? iterator()方法返回對此 set 中元素進行迭代的迭代器。返回元素的順序并不是特定的。底層調用HashMap的keySet返回所有的key,這點反應了HashSet中的所有元素都是保存在HashMap的key中,value則是使用的PRESENT對象,該對象為static final。
public int size() {
return map.size();
}
size()返回此 set 中的元素的數量(set 的容量)。底層調用HashMap的size方法,返回HashMap容器的大小。
public boolean contains(Object o) {
return map.containsKey(o);
}
?contains(),判斷某個元素是否存在于HashSet()中,存在返回true,否則返回false。
public Object clone() {
try {
HashSet newSet = (HashSet) super.clone();
newSet.map = (HashMap) map.clone();
return newSet;
} catch (CloneNotSupportedException e) {
throw new InternalError();
}
}
clone返回此 HashSet 實例的淺表副本:并沒有復制這些元素本身。
LinkedHashSet
?LinkedHashSet繼承自HashSet,源碼更少、更簡單,唯一的區別是LinkedHashSet內部使用的是LinkHashMap。這樣做的意義或者好處就是LinkedHashSet中的元素順序是可以保證的,也就是說遍歷序和插入序是一致的。
public class LinkedHashSet
extends HashSet
implements Set, Cloneable, java.io.Serializable {
?其內部的構造方法:
public LinkedHashSet(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor, true);
}
public LinkedHashSet(int initialCapacity) {
super(initialCapacity, .75f, true);
}
public LinkedHashSet() {
super(16, .75f, true);
}
public LinkedHashSet(Collection extends E> c) {
super(Math.max(2*c.size(), 11), .75f, true);
addAll(c);
}
?LinkedHashSet的父類是HashSet,其構造方法中調用的父類構造方法super,指的就是HashSet中這個默認訪問權限的構造器:
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
?可以看出LinkedHashSet內部使用的是LinkHashMap。這樣做的意義或者好處就是LinkedHashSet中的元素順序是可以保證的,也就是說遍歷序和插入序是一致的。
?LinkedHashMap 繼承自 HashMap,所以它的底層仍然是基于拉鏈式散列結構即由數組和鏈表或紅黑樹組成。另外,LinkedHashMap 在上面結構的基礎上,增加了一條雙向鏈表,使得上面的結構可以保持鍵值對的插入順序。同時通過對鏈表進行相應的操作,實現了訪問順序相關邏輯。
TreeSet
?TreeSet會對集合里的元素按照指定的順序進行排序,它的底層數據結構依據的是紅-黑二叉樹。如果想要往TreeSet集合中存入自定義類型的元素,有兩種方案:
?1、(自然排序)這個元素對應的類要么自身實現了Comparable接口,重寫了其中的compareTo方法,在方法內定義比較算法, 根據大小關系, 返回正數負數或零,在使用TreeSet存儲對象的時候, add()方法內部就會自動調用compareTo()方法進行比較, 根據比較結果使用二叉樹形式進行存儲。TreeSet方法保證元素唯一性的方式:就是參考比較方法的結果是否為0,如果return 0,視為兩個對象重復,不存儲。
?2、自定義一個比較器類,繼承Comparator,定義存入集合的元素是如何比較的。TreeSet,它根據指定比較器進行排序。插入到該set的所有元素都必須能夠由指定比較器進行相互比較:對于set中的任意兩個元素e1和e2,執行 comparator.compare(e1, e2) 都不得拋出 ClassCastException。如果用戶試圖將違反此約束的元素添加到 set 中,則add調用將拋出ClassCastException。
?如果存入集合的元素既不支持自身比較性,又沒有為這個集合傳入自定義的比較器對象,那么就會拋出異常:
Exception in thread "main" java.lang.ClassCastException: com.test2.B cannot be cast to java.lang.Comparable
?TreeSet是非同步的。TreeSet實際上是TreeMap實現的。TreeSet不支持快速隨機遍歷,只能通過迭代器進行遍歷!
比較HashSet、LinkedHashSet和TreeSet三者的異同
HashSet 是 Set 接口的主要實現類 ,HashSet 的底層是 HashMap,線程不安全的,可以存儲null值;
LinkedHashSet 是 HashSet 的子類,底層是LinkHashMap,能夠按照添加的順序遍歷;
TreeSet 底層使用紅黑樹,能夠按照按照某種規則對元素進行排序,排序的方式有自然排序和定制排序。集合中的元素是有序的,集合中的元素是唯一的。
原文:https://www.cnblogs.com/yxym2016/p/14515119.html
總結
以上是生活随笔為你收集整理的java 实现set,Java--Set的三个具体实现类的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java替换html特殊字符,HTML特
- 下一篇: matlab仿真生成信号程序,信号与系统