在上一節中我們介紹了 HashSet,雖然它能高效實現去重,但元素無序是其明顯短板。Java 集合框架提供了另一個關鍵實現 —— TreeSet,它基於紅黑樹結構,天然保證元素有序。與 HashSet 依賴 HashMap 類似,TreeSet 內部封裝了一個 TreeMap,所有操作最終委託給底層映射處理。
TreeSet 提供兩種核心構造方式:
public TreeSet() public TreeSet(Comparator<? super E> comparator)
無參構造要求元素實現 Comparable 接口(自然排序);帶比較器構造則允許自定義排序邏輯,元素無需實現 Comparable。
Set<String> words = new TreeSet<>();
words.addAll(Arrays.asList("tree", "map", "hash", "map"));
for (String w : words) {
System.out.print(w + " ");
}
// 輸出:hash map tree
程式碼展示了 TreeSet 同時實現「去重」與「升序排列」兩大核心功能。
Set<String> words = new TreeSet<>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareToIgnoreCase(o2);
}
});
words.addAll(Arrays.asList("tree", "map", "hash", "Map"));
System.out.println(words);
// 輸出:[hash, map, tree]
關鍵細節:Set 判重依賴比較器返回值,compare() == 0 視為重複。上例中 "map" 與 "Map" 忽略大小寫比較結果為 0,因此僅保留首個元素。
TreeSet 實現 SortedSet,提供豐富的有序操作:
first() / last():獲取首尾元素headSet(toElement):嚴格小於指定值的子集tailSet(fromElement):大於等於指定值的子集subSet(from, to):[from, to) 區間子集所有子集方法返回的是視圖,對視圖修改會直接影響原集合。
SortedSet<String> set = new TreeSet<>();
set.addAll(Arrays.asList("c", "a", "b", "d", "f"));
System.out.println(set.first()); // a
System.out.println(set.last()); // f
System.out.println(set.headSet("b")); // [a]
System.out.println(set.tailSet("d")); // [d, f]
System.out.println(set.subSet("b", "e")); // [b, c, d]
set.subSet("b", "e").clear(); // 刪除原集合中區間元素
System.out.println(set); // [a, f]
NavigableSet 繼承 SortedSet,新增精準邊界控制與反向操作:
floor(e) / lower(e):≤e / <e 的最大元素ceiling(e) / higher(e):≥e / >e 的最小元素pollFirst() / pollLast():彈出並移除首尾元素descendingSet() / descendingIterator():逆序視圖與迭代器NavigableSet<String> set = new TreeSet<>();
set.addAll(Arrays.asList("c", "a", "b", "d", "f"));
System.out.println(set.floor("a")); // a
System.out.println(set.lower("b")); // a
System.out.println(set.ceiling("d")); // d
System.out.println(set.higher("c")); // d
System.out.println(set.subSet("b", true, "d", true)); // [b, c, d] 含邊界
System.out.println(set.pollFirst()); // a
System.out.println(set.pollLast()); // f
System.out.println(set.descendingSet()); // [d, c, b]
public TreeSet(Collection<? extends E> c) // 自然排序複製集合 public TreeSet(SortedSet<E> s) // 複製並繼承比較器 TreeSet(NavigableMap<E, Object> m) // 內部包裝構造(非 public)
private transient NavigableMap<E, Object> m; private static final Object PRESENT = new Object();
m 是底層 TreeMap,PRESENT 作為統一佔位值。
| 操作 | TreeSet 實現 | 委託目標 |
|---|---|---|
| add(e) | m.put(e, PRESENT) == null | TreeMap.put() |
| contains(o) | m.containsKey(o) | TreeMap.containsKey() |
| remove(o) | m.remove(o) == PRESENT | TreeMap.remove() |
| subSet(...) | new TreeSet<>(m.subMap(...)) | TreeMap.subMap() |
| first()/last() | m.firstKey()/lastKey() | TreeMap.firstKey()/lastKey() |
| pollFirst()/pollLast() | 調用 m.pollFirstEntry()/pollLastEntry() 取鍵 | TreeMap.pollFirstEntry()/pollLastEntry() |
| descendingIterator() | m.descendingKeySet().iterator() | TreeMap.descendingKeySet() |
TreeMap)vs 哈希表(HashMap)O(log N) vs 平均 O(1)Comparable 或提供 Comparator vs 需正確重寫 hashCode()/equals()O(log N) 性能可接受至此,Java 主流集合容器(List、Set、Map、Queue/Deque)及核心實現類(ArrayList、LinkedList、HashMap、TreeMap、HashSet、TreeSet)已全部介紹完畢。後續將探討更多特色實現類。
---------------
未完待續,查看最新文章,敬請關注微信公眾號“老馬說編程”(掃描下方二維碼),從入門到高級,深入淺出,老馬和你一起探索 Java 編程及計算機技術的本質。用心原創,保留所有版權。
