首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java Set 接口深度解析:HashSet、TreeSet、LinkedHashSet 核心原理與去重機制

     編輯:Java 相關知識

Set 接口核心特性

  • 不允許重複元素:數學集合「互異性」
  • 元素無順序:數學集合「無序性」(LinkedHashSet 維護插入序,TreeSet 維護排序序)
  • 最多一個 null 元素

三大實作類別比較

實作類底層結構順序特性效能特點適用場景
HashSetHashMap(雜湊表)無序增刪查 O(1) 最快高頻去重、不需排序
LinkedHashSetHashMap + 雙向鏈表維護插入順序略慢於 HashSet,但有序需保留插入序的去重
TreeSetTreeMap(紅黑樹)維護自然/客製排序增刪查 O(log n)需排序、區間查詢

去重核心機制:hashCode() 與 equals() 契約

Java 集合判斷兩物件是否相等的雙重檢查:

  1. 先比 hashCode():不同 → 直接判定不相等;相同 → 進入步驟 2
  2. 再呼叫 equals():回傳 true → 判定相等(去重);false → 不相等

⚠️ 關鍵規則

  • 重寫 equals() 必須重寫 hashCode(),否則違反契約導致 Set/Map 失效
  • 相等物件必須有相同 hashCode;hashCode 相等物件不一定相等
  • String、Integer 等包裝類已正確重寫,直接可用

程式碼實戰範例

1. HashSet:自訂物件去重

class Student {
    int id;
    public Student(int id) { this.id = id; }
    
    @Override public int hashCode() { return id; }
    @Override public boolean equals(Object obj) {
        return obj instanceof Student && ((Student)obj).id == this.id;
    }
    @Override public String toString() { return "Student[" + id + "]"; }
}

Set<Student> set = new HashSet<>();
set.add(new Student(1));
set.add(new Student(1)); // 重複,不會加入
set.add(new Student(2));
// 輸出:Student[1], Student[2]

2. TreeSet:自然排序

class Student implements Comparable<Student> {
    int id;
    // ... 建構子、hashCode、equals 同上
    @Override public int compareTo(Student o) { return this.id - o.id; }
}

Set<Student> set = new TreeSet<>();
set.add(new Student(5));
set.add(new Student(1));
set.add(new Student(3));
// 輸出:Student[1], Student[3], Student[5](自動升序)

3. TreeSet:客製排序

class DescComparator implements Comparator<Student> {
    public int compare(Student o1, Student o2) { return o2.id - o1.id; }
}

Set<Student> set = new TreeSet<>(new DescComparator());
// 輸出:Student[5], Student[3], Student[1](降序)

4. List 同樣可排序

List<Student> list = new ArrayList<>();
// ... 添加 5,1,2,4,3
Collections.sort(list);           // 自然排序 → [1,2,3,4,5]
Collections.sort(list, new DescComparator()); // 客製排序 → [5,4,3,2,1]

常見陷阱與最佳實踐

陷阱後果解決方案
只重寫 equals() 不重寫 hashCode()HashSet/HashMap 視為不同物件,去重失效配對重寫,IDE 產生
可變物件放入 Set 後修改屬性hashCode 改變導致找不到元素,記憶體洩漏使用不可變物件,或修改前 remove 再 add
TreeSet 存入未實作 Comparable 物件執行期拋出 ClassCastException實作 Comparable 或提供 Comparator

總結選型建議

  • 單純去重、高頻查詢 → HashSet
  • 需保留插入順序 → LinkedHashSet
  • 需排序、範圍查詢(subSet、headSet、tailSet) → TreeSet
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved