Set接口
首先Set集合不能擁有相同的元素,它與Collection的方法上沒有太多的差別,隻是行為不同,即不能有相同元素.
HashSet實作類
HashSet是Set的接口的典型實作,大多數時都會使用HashSet,使用的時Hash算法來存儲集合中的元,是以有很好的存取和查找性能.
HashSet的特點:
1.不能保證元素的排列順序,順序可能和添加順序不同,可能會有變化
2.HashSet不是同步的,可以通過代碼保證其同步
3.集合的元素值可以是null
當一個HashSet集合存入一個元素時,HashSet會調用該對象的hashCode()方法來得到hashCode值,根據值決定HashSet中的存儲位置.
但如果當兩對象的hashCode值不相等,則不會調用equal()方法,即就算兩者的值是相等,HashSet會将它們存儲在不同位置,依然可以添加成功,這是不可取的,違反了Set的規則
當兩對象的hashCode值相等,調用equal值不相等時,HashSet将會試圖将它們使用鍊式結構儲存在同一位置,但這種情況會導緻HashSet的性能下降,因為HashSet是根據元素的hashCode值來快速定位的
是以當某個類的對象儲存到HashSet集合中,重寫這個類的equals()方法和hashCode()方法時,應盡量保證兩個對象通過equals()方法比較傳回true時,他們的hashCode()方法傳回值也為true
當HashSet集合中添加了可變對象也要極其小心,若是修改了集合元素中參與計算hashCode(),equals()的執行個體變量,可能會導緻HashSet無法正确操作這些集合元素,如下
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class HashSetTest {
public static void main(String[] args) {
Set hs = new HashSet();
hs.add(new A(1));
hs.add(new A(5));
hs.add(new A(10));
hs.add(new A(20));
System.out.println("原來中集合的元素:"+hs+" ");
System.out.println("-------------------------");
Iterator it = hs.iterator();
//取出第一個元素
A one = (A) it.next();
one.count = 5;
System.out.println("修改後的集合元素:"+ hs + " ");
System.out.println("-------------------------");
//删除一個count為5的對象
hs.remove(new A(5));
System.out.println("删除了一個集合元素為5的元素:" + hs + " ");
System.out.println("-------------------------");
System.out.println("是否包含了1的對象:" +hs.contains(new A(1)));
System.out.println("是否包含了5的對象:" +hs.contains(new A(5)));
}
}
控制台列印結果
原來中集合的元素:[A的count值:1, A的count值:20, A的count值:5, A的count值:10]
-------------------------
修改後的集合元素:[A的count值:5, A的count值:20, A的count值:5, A的count值:10]
-------------------------
删除了一個集合元素為5的元素:[A的count值:5, A的count值:20, A的count值:10]
-------------------------
是否包含了1的對象:false
是否包含了5的對象:false
LinkedHashSet
LinkedHashSet是HashSet的子類,它與HashSet的差別是,元素的順序總是與添加的順序,這是使用了連結清單維護元素的次序,是以性能略低于HashSet的性能,但在疊代通路Set裡的全部元素時将有很好的性能,因為它以連結清單來維護内部順序.
TreeSet
TreeSet是SortSet接口的實作類,TreeSet不是以插入順序進行排序的,而是根據元素實際值的大小來進行排序的.
TreeSet會調用集合元素的compareTo(Object obj)方法來比較元素之間的大小的關系,然後将集合元素按升序排序,為自然排序.
Java9改進了TreeSet實作,采用自然排序的Set集合的元素沒有實作Comparable,程式會引發ClassCaseException異常
TreeSet和HashSet一樣不要修改執行個體變量,會導緻無法删除變量,為了讓程式健壯,不要修改放入HashSet和TreeSet集合中元素的關鍵執行個體變量.
定制排序,可以通過Comparator接口的幫助來制定自己的排序代碼
EnumSet
EnumSet是一個轉為枚舉類的集合類,EnumSet中所有的元素都必須是指定的枚舉類型的枚舉值,其集合元素也是有序的,EnumSet以枚舉在Enum類内的定義順序來決定集合元素的順序.
EnumSet在内部以位向量的形式存儲,這種存儲形式非常緊湊,高效,是以EnumSet對象占用記憶體很小,而且運作效率好.
EnumSet步允許加入null元素
各Set實作類的性能分析
HashSet和TreeSet是Set兩個典型實作,HashSet的性能總比TreeSet好,特别是在添加,查詢元素等操作,因為TreeSet需要額外的紅黑數算法來維護集合元素的次序.
LinkedHashSet因為有了連結清單的維護,在周遊時會比較友善
EnumSet性能最好
上述的Set的實作類,線程都是不安全的,可以通過Collections.synchronizedSortedSet()來實作線程安全