TreeSet是什么
TreeSet 是 Java 中 Set 接口的一个实现,基于 [[二叉树|红黑树(Red-Black Tree)]] 结构,用于存储无重复且有序的元素。它自动维护元素的排序顺序,并支持高效的查找、插入和删除操作。
- 底层使用红黑树结构
- 去重、排序(拿树中已存在的元素和要存储的元素比较【比较大小:0、正数(右节点)、负数(左节点)】)
- 不能存储重复元素
- 没有索引
- 每个元素被存入时,会按照 自然排序(
Comparable) 或 自定义排序(Comparator) 进行排列。
- 插入、删除、查找的时间复杂度是 **O(log n)**,因为红黑树保持了平衡。
TreeSet如何判断元素的唯一性?
在 TreeSet 中,元素的唯一性由二叉搜索树(红黑树)的规则决定:
- 如果
compareTo()(Comparable) 或 compare()(Comparator) 返回 0,则认为两个元素相等,新元素不会被加入。
- 如果返回负数或正数,则新元素被插入到树的不同位置。
通过[[Comparable和Comparator|Comparable]]实现唯一性
如果类实现了 Comparable<T>,那么 TreeSet 会调用 compareTo() 方法进行元素比较。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
| import java.util.Objects; public class Person implements Comparable<Person> { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } @Override public int hashCode() { return Objects.hash(name, age); } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null || getClass() != obj.getClass()) return false; Person person = (Person) obj; return age == person.age && Objects.equals(name, person.name); } @Override public int compareTo(Person o) { if (this == o) return 0; int res = this.name.compareTo(o.name); return (res != 0) ? res : Integer.compare(this.age, o.age); } @Override public String toString() { return "Person{name='" + name + "', age=" + age + '}'; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
import java.util.TreeSet; public class Main { public static void main(String[] args) { TreeSet<Person> set = new TreeSet<Person>(); Person aaa = new Person("aaa", 18); set.add(aaa); set.add(new Person("ccc", 19)); set.add(new Person("bbb", 16)); set.add(new Person("aaa", 20)); set.add(aaa); for (Person person : set) { System.out.println(person); } } }
|
输出结果:
1 2 3 4
| Person{name='aaa', age=18} Person{name='aaa', age=20} Person{name='bbb', age=16} Person{name='ccc', age=19}
|
通过[[Comparable和Comparator|Comparator]]自定义唯一性
如果类**没有实现 Comparable**,可以使用 Comparator 自定义比较规则。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| import java.util.*;
class Employee { String name; int salary;
public Employee(String name, int salary) { this.name = name; this.salary = salary; }
@Override public String toString() { return name + "($" + salary + ")"; } }
public class CustomComparatorExample { public static void main(String[] args) { TreeSet<Employee> employees = new TreeSet<>(Comparator.comparingInt(e -> e.salary));
employees.add(new Employee("Alice", 5000)); employees.add(new Employee("Bob", 6000)); employees.add(new Employee("Charlie", 5000));
System.out.println(employees); } }
|
使用注意
hashCode() 和 equals() 不会影响元素的唯一性。
- 但如果对象可能**同时存入
HashSet 和 TreeSet**,建议 equals() 和 compareTo() 逻辑一致,防止数据不一致。