Java集合——Set

一、綜述

\quadSet集合包含三個常用的類——HashSet, TreeSet, EnumSet,這三個類各有特色,使用場景不同。這裏先討論Set集合的通用特性:

  • Set集合與Collection基本一樣,沒有提供額外的方法,只是行爲不同
  • Set集合不允許有相同的元素,如果試圖把兩個相同的元素加入一個Set集合則添加操作失敗,add方法將返回false
  • Set判斷兩個對象相同不是使用==運算符,而是使用equals方法

二、HashSet

\quadHashSet具有以下特點:

  • 不能保證元素的排列順序
  • 集合元素可以是null

\quad當向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]
    }
}

\quad如上面程序所示:HashSet集合中第一個元素和第三個元素完全相同,這表明兩個元素已經重複,但因爲HashSet在添加它們時將其添加到了不同的位置,所以HashSet完全可以容納兩個相同的元素。但此時HashSet將會很混亂,當試圖刪除count=9的對象時HashSet會計算出該對象的hashCode值,從而找出該對象在集合中的保存位置,這樣可以刪除最後一個元素。當繼續想刪除第一個元素——count=9的元素時會發現無法刪除,因爲現在其所處位置是之前count=-3所在的位置,這樣就造成了無法精確定位!
\quadHashSet還有一個子類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

\quadTreeSet是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]
    }
}
發佈了222 篇原創文章 · 獲贊 99 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章