目录
前言
在 Java 的集合框架中,Set 接口代表了一个不允许存在重复元素的集合。我们最常用的通常是 HashSet,因为它提供了极高的查找和插入效率。但是,当我们不仅需要去重,还需要保证集合元素有序时,TreeSet 就成了不二之选。
一、TreeSet的特点
- 不重复、无索引、可排序
- 可排序:按照元素的默认规则(由小到大)进行排序。
- TreeSet集合底层是基于红黑树的数据结构实现排序的,增删改查性能都比较好。
排序的具体场景:
java
public class Test {
public static void main(String[] args) {
TreeSet<Integer> ts = new TreeSet<>();
ts.add(5);
ts.add(3);
ts.add(2);
ts.add(1);
ts.add(4);
System.out.println(ts);
//迭代器遍历
Iterator<Integer> it = ts.iterator();
while(it.hasNext()){
int i = it.next();
System.out.println(i);
}
//增强for遍历
for (Integer i : ts) {
System.out.println(i);
}
//Lambda表达式遍历
ts.forEach(integer-> System.out.println(integer));
}
}
二、TreeSet集合默认的规则
- 对于数值类型:Integer、Double,默认是按照数字的从小到大的顺序进行排序。
- 对于字符、字符串类型:按照字符在ASCII码表中的数字进行升序排序的。
对于"aaa"、"ab"这两个字符串在对比时,跟字符串的长度是无关的,对比规则为,从第一个字符开始对应比较,一旦有一个字符能够确定大小关系,那么整个字符串的大小关系也随之确定。
1.默认排序/自然排序
JavaBean类实现Comparable接口指定比较规则。
当我们存入引用类型数据时,会发生什么?
Student JavaBean类:
java
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
this.age = age;
}
public String toString() {
return "Student{name = " + name + ", age = " + age + "}";
}
}
当我们直接添加、打印输出时会发生什么?

由于编译器并不知道根据什么来排序,因此会报错。
解决方法:我们需要在Student类中重写compareTo方法。


运行结果:

compareTo方法:
this:表示当前要添加的元素。
o:表示已经存在于红黑树的元素。
返回值:
负数:认为要添加的元素是小的,存左边。
正数:认为要添加的元素是大的,存右边。
0:认为要添加的元素已经存在,舍弃。
2.比较器排序
创建TreeSet对象时,传递比较器Comparator指定规则。

java
public class Test {
public static void main(String[] args) {
TreeSet<String> ts = new TreeSet<>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return 0;
}
});
}
}
案例:
存入字符串"c"、"ab"、"df"、"qwer",按照长度排序,如果一样长则按照首字母排序。
java
public class Test {
public static void main(String[] args) {
TreeSet<String> ts = new TreeSet<>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
//按长度排序
int i = o1.length() - o2.length();
int result = i == 0 ? o1.compareTo(o2) : i;
return result;
}
});
ts.add("c");
ts.add("ab");
ts.add("qwer");
ts.add("df");
System.out.println(ts);
}
}
运行结果:

总结
TreeSet集合的特点:
- 可排序、不重复、无索引
- 底层基于红黑树实现排序,增删改查性能好
TreeSet集合自定义排序规则:
- 方式一:JavaBean类实现Comparable接口,指定比较规则。
- 方式二:创建集合时,自定义Comparator比较器对象,指定比较规则。
方法返回值的特点:
- 负数:认为要添加的元素是小的,存左边。
- 正数:认为要添加的元素是大的,存右边。
- 0:认为要添加的元素已经存在,舍弃。
😎🤗