一、綜述
Set集合包含三個常用的類——HashSet, TreeSet, EnumSet
,這三個類各有特色,使用場景不同。這裏先討論Set集合的通用特性:
- Set集合與Collection基本一樣,沒有提供額外的方法,只是行爲不同
- Set集合不允許有相同的元素,如果試圖把兩個相同的元素加入一個Set集合則添加操作失敗,add方法將返回false
- Set判斷兩個對象相同不是使用
==
運算符,而是使用equals
方法
二、HashSet
HashSet具有以下特點:
- 不能保證元素的排列順序
- 集合元素可以是null
當向HashSet集合中放入一個元素時,HashSet會調用該對象的hashCode()
方法來得到該對象的hashCode值,然後根據該值決定該元素在HashSet中的存儲位置。下面程序演示瞭如何在HashSet集合內放入對象,通過修改還能在集合內放入兩個相同的對象(equals函數相同且hashCode值也相同)。
import java.util.HashSet;
import java.util.Iterator;
public class TestHashSet {
int count;
public TestHashSet(int count) { this.count = count; }
// 重寫toString方法用於打印輸出
public String toString() { return "Count=" + count; }
// 重寫equals和hashCode方法
public boolean equals(Object obj) {
if(obj instanceof TestHashSet)
{
TestHashSet t = (TestHashSet) obj;
if(t.count == this.count) return true;
}
return false;
}
public int hashCode() { return this.count; }
public static void main(String[] args)
{
HashSet set = new HashSet();
set.add(new TestHashSet(5));
set.add(new TestHashSet(-3));
set.add(new TestHashSet(9));
set.add(new TestHashSet(9));
System.out.println(set); // [Count=-3, Count=5, Count=9]
// 取出第一個元素並將其count值改爲9
Iterator it = set.iterator();
TestHashSet t = (TestHashSet) it.next();
t.count = 9;
System.out.println(set); // [Count=9, Count=5, Count=9]
// 刪除值爲9的對象,將會刪除第三個元素
set.remove(new TestHashSet(9));
System.out.println(set); // [Count=9, Count=5]
// 刪除值爲9的對象,無法刪除第一個元素,因爲其所放位置在之前count=-3的位置上
set.remove(new TestHashSet(9));
System.out.println(set); // [Count=9, Count=5]
}
}
如上面程序所示:HashSet集合中第一個元素和第三個元素完全相同,這表明兩個元素已經重複,但因爲HashSet在添加它們時將其添加到了不同的位置,所以HashSet完全可以容納兩個相同的元素。但此時HashSet將會很混亂,當試圖刪除count=9的對象時HashSet會計算出該對象的hashCode值,從而找出該對象在集合中的保存位置,這樣可以刪除最後一個元素。當繼續想刪除第一個元素——count=9的元素時會發現無法刪除,因爲現在其所處位置是之前count=-3所在的位置,這樣就造成了無法精確定位!
HashSet還有一個子類LinkedHashSet
,該集合也是根據元素的hashCode
值來決定元素的存儲位置,但它同時使用鏈表維護元素的次序,這樣使得元素看起來是以插入的順序保存的。因爲需要維護插入順序,故其性能略低於HashSet的性能。舉個例子:
import java.util.LinkedHashSet;
public class TestLinkedHashSet {
public static void main(String[] args)
{
LinkedHashSet books = new LinkedHashSet();
books.add("Java瘋狂筆記");
books.add("代碼整潔之道");
books.add("防脫髮指南");
books.add("Java瘋狂筆記");
System.out.println(books); // [Java瘋狂筆記, 代碼整潔之道, 防脫髮指南]
}
}
三、TreeSet
TreeSet是SortedSet的唯一實現,可以確保集合元素處於排序狀態。與前面HashSet相比,TreeSet還提供瞭如下額外的方法:
comparator comparator()
:返回當前Set使用的Comparator
Object first
:返回集合中第一個元素Object last
:返回集合中最後一個元素Object lower(Object e)
:返回小於e的最大元素Object higher(Object e)
:返回大於e的最小元素SortedSet subSet(fromElement, toElement)
:返回Set的子集,元素範圍爲[fromElement, toElement)SortedSet headSet(toElement)
:返回Set的子集,元素範圍爲[負無窮, toElement)SortedSet tailSet(fromElement)
:返回Set的子集,元素範圍爲[fromElement, 正無窮)
import java.util.TreeSet;
public class TestTreeSet {
public static void main(String[] args)
{
TreeSet ts = new TreeSet();
ts.add(3); ts.add(1); ts.add(5); ts.add(2); ts.add(4);
System.out.println(ts.first()); // 1
System.out.println(ts.last()); // 5
System.out.println(ts.lower(3)); // 2
System.out.println(ts.higher(3)); // 4
System.out.println(ts.subSet(1, 4)); // [1, 2, 3]
System.out.println(ts.headSet(4)); // [1, 2, 3]
System.out.println(ts.tailSet(4)); // [4, 5]
}
}