Java TreeSet 排序案例
TreeSet 提供了两种排序方式:自然排序 和 定制排序,我来给你展示具体的案例代码。

自然排序(Comparable接口)
import java.util.TreeSet;
// 学生类实现Comparable接口
class Student implements Comparable<Student> {
private String name;
private int age;
private double score;
public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
}
// 实现compareTo方法,按年龄排序
@Override
public int compareTo(Student other) {
// 先按年龄排序
int ageCompare = Integer.compare(this.age, other.age);
if (ageCompare != 0) {
return ageCompare;
}
// 年龄相同时按成绩排序
return Double.compare(this.score, other.score);
}
@Override
public String toString() {
return "Student{name='" + name + "', age=" + age + ", score=" + score + "}";
}
}
public class TreeSetNaturalSortDemo {
public static void main(String[] args) {
TreeSet<Student> students = new TreeSet<>();
students.add(new Student("张三", 20, 85.5));
students.add(new Student("李四", 18, 90.0));
students.add(new Student("王五", 22, 78.0));
students.add(new Student("赵六", 20, 95.0));
students.add(new Student("张三", 20, 85.5)); // 重复元素,不会被添加
System.out.println("TreeSet元素(按年龄排序):");
for (Student s : students) {
System.out.println(s);
}
}
}
定制排序(Comparator接口)
import java.util.Comparator;
import java.util.TreeSet;
public class TreeSetCustomSortDemo {
public static void main(String[] args) {
// 方式1:使用匿名内部类
TreeSet<Student> students1 = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
// 按成绩降序排序
int scoreCompare = Double.compare(s2.getScore(), s1.getScore());
if (scoreCompare != 0) {
return scoreCompare;
}
// 成绩相同时按姓名排序
return s1.getName().compareTo(s2.getName());
}
});
// 添加学生
students1.add(new Student("张三", 20, 85.5));
students1.add(new Student("李四", 18, 90.0));
students1.add(new Student("王五", 22, 78.0));
students1.add(new Student("赵六", 20, 95.0));
System.out.println("按成绩降序排序:");
for (Student s : students1) {
System.out.println(s);
}
// 方式2:使用Lambda表达式(Java 8+)
TreeSet<Student> students2 = new TreeSet<>(
(s1, s2) -> {
// 先按姓名排序
int nameCompare = s1.getName().compareTo(s2.getName());
if (nameCompare != 0) {
return nameCompare;
}
// 姓名相同时按年龄排序
return Integer.compare(s1.getAge(), s2.getAge());
}
);
students2.add(new Student("张三", 20, 85.5));
students2.add(new Student("张三", 18, 90.0));
students2.add(new Student("李四", 22, 78.0));
System.out.println("\n按姓名升序,姓名相同按年龄:");
for (Student s : students2) {
System.out.println(s);
}
}
}
// 完善Student类,增加getter方法
class Student implements Comparable<Student> {
private String name;
private int age;
private double score;
public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
}
public String getName() { return name; }
public int getAge() { return age; }
public double getScore() { return score; }
@Override
public int compareTo(Student other) {
int ageCompare = Integer.compare(this.age, other.age);
if (ageCompare != 0) {
return ageCompare;
}
return Double.compare(this.score, other.score);
}
@Override
public String toString() {
return "Student{name='" + name + "', age=" + age + ", score=" + score + "}";
}
}
字符串自定义排序案例
import java.util.Comparator;
import java.util.TreeSet;
public class StringSortDemo {
public static void main(String[] args) {
// 案例1:按字符串长度排序
TreeSet<String> lengthSort = new TreeSet<>(
(s1, s2) -> {
int lenCompare = Integer.compare(s1.length(), s2.length());
if (lenCompare != 0) {
return lenCompare;
}
// 长度相同时按字母顺序
return s1.compareTo(s2);
}
);
lengthSort.add("Java");
lengthSort.add("Python");
lengthSort.add("C");
lengthSort.add("JavaScript");
lengthSort.add("Go");
System.out.println("按字符串长度排序:");
for (String s : lengthSort) {
System.out.println(s + " (长度: " + s.length() + ")");
}
// 案例2:忽略大小写排序
TreeSet<String> caseInsensitiveSort = new TreeSet<>(
String.CASE_INSENSITIVE_ORDER
);
caseInsensitiveSort.add("Apple");
caseInsensitiveSort.add("banana");
caseInsensitiveSort.add("Cherry");
caseInsensitiveSort.add("date");
System.out.println("\n忽略大小写排序:");
for (String s : caseInsensitiveSort) {
System.out.println(s);
}
}
}
复杂对象多字段排序
import java.util.*;
class Employee {
private String name;
private String department;
private double salary;
private int age;
public Employee(String name, String department, double salary, int age) {
this.name = name;
this.department = department;
this.salary = salary;
this.age = age;
}
// getter方法
public String getName() { return name; }
public String getDepartment() { return department; }
public double getSalary() { return salary; }
public int getAge() { return age; }
@Override
public String toString() {
return String.format("%-8s | 部门:%-6s | 薪资:%.1f | 年龄:%d",
name, department, salary, age);
}
}
public class MultiFieldSortDemo {
public static void main(String[] args) {
// 多字段排序:先按部门,再按薪资降序,最后按年龄
TreeSet<Employee> employees = new TreeSet<>(
Comparator.comparing(Employee::getDepartment)
.thenComparing(Employee::getSalary, Comparator.reverseOrder())
.thenComparing(Employee::getAge)
);
employees.add(new Employee("张三", "技术部", 15000, 28));
employees.add(new Employee("李四", "市场部", 12000, 25));
employees.add(new Employee("王五", "技术部", 18000, 32));
employees.add(new Employee("赵六", "市场部", 12000, 27));
employees.add(new Employee("钱七", "技术部", 15000, 30));
System.out.println("多字段排序(部门→薪资降序→年龄):");
System.out.println("姓名 | 部门 | 薪资 | 年龄");
System.out.println("-".repeat(45));
for (Employee e : employees) {
System.out.println(e);
}
}
}
注意事项
public class TreeSetNoteDemo {
public static void main(String[] args) {
// 1. 不能存储null元素
TreeSet<String> set = new TreeSet<>();
// set.add(null); // 会抛出NullPointerException
// 2. 自定义对象必须实现Comparable或提供Comparator
// 3. compareTo/compare返回0表示元素重复,不会添加
// 4. 排序规则应满足一致性(传递性、自反性等)
// 5. 使用Comparator.of方法优雅组合比较器
TreeSet<String> words = new TreeSet<>(
Comparator.comparingInt(String::length)
.thenComparing(String::compareToIgnoreCase)
.reversed() // 反转整个排序
);
words.add("apple");
words.add("banana");
words.add("cherry");
words.add("date");
words.add("elderberry");
System.out.println("按长度降序,长度相同忽略大小写:");
words.forEach(System.out::println);
}
}
| 排序方式 | 实现方法 | 适用场景 |
|---|---|---|
| 自然排序 | 实现 Comparable 接口的 compareTo() |
对象有默认排序规则 |
| 定制排序 | 创建 Comparator 对象传入构造器 |
需要多种排序方式或临时排序 |
关键点:
- TreeSet 元素必须可比较
- 多个排序字段时使用
Comparator.thenComparing() compareTo/compare返回0视为重复元素- 使用Lambda可以简化代码