TreeSet 是基於紅黑樹實現的有序集合,元素不重複且按特定順序排列。要掌握它,必須理解兩大比較機制:自然順序(Comparable)與定製順序(Comparator)。
public class Person implements Comparable<Person> {
private String name;
private int age;
// 構造器、getter/setter、equals/hashCode/toString 略
@Override
public int compareTo(Person o) {
// 先按年齡升序,同年齡按姓名字典序
int ageDiff = this.age - o.age;
return (ageDiff == 0) ? this.name.compareTo(o.name) : ageDiff;
}
}
關鍵點:
Comparable<T> 泛型接口,避免強轉。compareTo 返回負/零/正分別表示小於/等於/大於。equals 保持一致:compareTo==0 應等價於 equals==true,否則違反 Set 契約。public class ComparatorByName implements Comparator<Person> {
@Override
public int compare(Person p1, Person p2) {
// 先按姓名,再按年齡
int nameCmp = p1.getName().compareTo(p2.getName());
return (nameCmp == 0) ? p1.getAge() - p2.getAge() : nameCmp;
}
}
優勢:不修改原類、可定義多種排序邏輯、適用於無法修改源碼的類。
public class TreeSetDemo {
public static void main(String[] args) {
// 使用 Comparator 定製排序
TreeSet<Person> ts = new TreeSet<>(new ComparatorByName());
ts.add(new Person("zhangsan", 28));
ts.add(new Person("lisi", 21));
ts.add(new Person("zhouqi", 29));
ts.add(new Person("zhaoliu", 25));
ts.add(new Person("wangwu", 24));
ts.add(new Person("lisi", 21)); // 重複元素(equals 相同)不會添加
ts.add(new Person("zhouqi", 29)); // 同上
// 輸出結果:按姓名字典序排列
ts.forEach(System.out::println);
}
}
輸出順序:lisi:21 → wangwu:24 → zhaoliu:25 → zhangsan:28 → zhouqi:29
核心規則:Comparator 優先於 Comparable;若構造器未傳 Comparator,則要求元素實現 Comparable,否則拋 ClassCastException。
Comparable。Comparator 實例。Comparator.comparing(Person::getName).thenComparing(Person::getAge) 鏈式構建,代碼更簡潔。