springboot注解
song

TreeSet是什么

TreeSet 是 Java 中 Set 接口的一个实现,基于 [[二叉树|红黑树(Red-Black Tree)]] 结构,用于存储无重复且有序的元素。它自动维护元素的排序顺序,并支持高效的查找、插入和删除操作。

  • 底层使用红黑树结构
    • 去重、排序(拿树中已存在的元素和要存储的元素比较【比较大小:0、正数(右节点)、负数(左节点)】)
  • 不能存储重复元素
  • 没有索引
  • 每个元素被存入时,会按照 自然排序(Comparable自定义排序(Comparator 进行排列。
  • 插入、删除、查找的时间复杂度是 **O(log n)**,因为红黑树保持了平衡。

TreeSet如何判断元素的唯一性?

TreeSet 中,元素的唯一性由二叉搜索树(红黑树)的规则决定:

  1. 如果 compareTo()Comparable) 或 compare()Comparator) 返回 0,则认为两个元素相等,新元素不会被加入
  2. 如果返回负数或正数,则新元素被插入到树的不同位置。

通过[[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) {
//比较大小 0表示相同 负数表示小 整数表示大
if (this == o) return 0;
// 先按 name 排序,name 相同时按 age 排序
int res = this.name.compareTo(o.name);
return (res != 0) ? res : Integer.compare(this.age, o.age);
// return (res != 0) ? res : this.age - o.age;
}

@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + '}';
}

// Getters and Setters
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); // 输出:[Alice($5000), Bob($6000)]
}
}

使用注意

  • hashCode()equals() 不会影响元素的唯一性
  • 但如果对象可能**同时存入 HashSetTreeSet**,建议 equals()compareTo() 逻辑一致,防止数据不一致。
由 Hexo 驱动 & 主题 Keep