TreeSet
TreeSet 属于 Set 接口实现类自带去重 自动排序和 HashSet、LinkedHashSet 去重机制完全不一样不依赖 hashCode () 和 equals ()依靠比较规则判定重复。 两种排序方案自然排序Comparable、比较器排序Comparator一、TreeSet 基础特点底层红黑树平衡二叉搜索树两大核心特性✅ 元素不重复去重、✅ 元素自动排序无索引不能用普通 for 循环遍历遍历方式同样是迭代器、增强 for、forEach (Lambda)不能存入 null会抛出空指针异常和 HashSet、LinkedHashSet 区分线程不安全排序规则二选一自然排序元素类实现Comparable接口默认方式比较器排序构造 TreeSet 时传入Comparator比较器优先级高于自然排序课堂重点区分HashSet无序哈希表靠 hashCodeequals 去重LinkedHashSet存取有序哈希表 双向链表靠 hashCodeequals 去重TreeSet大小排序红黑树靠比较方法返回值去重判定重复的规则必考调用比较方法返回 0 → 判定为重复元素不存入集合返回正数当前元素大放到右子树返回负数当前元素小放到左子树返回 0相等去重舍弃二、方式 1自然排序 Comparable默认使用无参构造new TreeSet()要求存入的实体类实现ComparableE接口重写compareTo()方法。 JDK 自带类Integer、String 已经实现 Comparable可以直接放进 TreeSet 自定义类Student必须手动实现 Comparable否则直接抛 ClassCastException 类型转换异常示例Student 实体类按照年龄升序排序年龄相同按 id 升序import java.util.Objects; // 实现Comparable接口指定比较类型 class Student implements ComparableStudent{ private Integer id; private String name; private int age; public Student() {} public Student(Integer id, String name, int age) { this.id id; this.name name; this.age age; } // get、set public Integer getId() { return id; } public void setId(Integer id) { this.id id; } 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; } Override public String toString() { return Student{id id , name name , age age }; } // 核心重写compareTo定义排序规则 Override public int compareTo(Student o) { // 规则优先按年龄升序 int res this.age - o.age; // 如果年龄相等再比较idid升序 res res 0 ? this.id - o.id : res; return res; // 【降序写法】 return o.age - this.age; } }测试代码TreeSetStudent treeSet new TreeSet(); treeSet.add(new Student(1001,张三,18)); treeSet.add(new Student(1003,李四,16)); treeSet.add(new Student(1002,王五,18)); // Lambda遍历 treeSet.forEach(System.out::println);输出顺序李四 (16) → 张三 (18) → 王五 (18)课堂要点如果只比较 ageage 相同返回 0就会判定为同一个学生直接去重所以多字段比较是常用写法。三、方式 2比较器排序 Comparator优先级更高使用带参构造new TreeSet(Comparator比较器)优势不用修改实体类代码灵活切换排序规则同一个实体类可以写多种排序逻辑 支持匿名内部类、Lambda 表达式课堂重点Lambda 简化写法// 1.匿名内部类写法 TreeSetStudent tree1 new TreeSet(new ComparatorStudent() { Override public int compare(Student s1, Student s2) { // 按年龄降序年龄相同按名字排序 int res s2.getAge() - s1.getAge(); res res 0 ? s1.getName().compareTo(s2.getName()) : res; return res; } }); // 2.Lambda简写课堂推荐简洁写法 TreeSetStudent tree2 new TreeSet((s1,s2)-{ int res s2.getAge() - s1.getAge(); res res 0 ? s1.getName().compareTo(s2.getName()) : res; return res; });优先级Comparator 比较器排序 Comparable 自然排序两个都写的时候以 Comparator 为准。四、三种 Set 实现类完整对比表集合底层结构顺序特点去重依据能否存 null效率HashSet哈希表 (数组 链表 红黑树)无序hashCode()equals()✅ 最多 1 个读写最快LinkedHashSet哈希表 双向链表存取有序添加顺序hashCode()equals()✅ 最多 1 个中等维护链表TreeSet红黑树元素大小排序compareTo /compare 返回值❌ 不能存 null较慢需要排序五、TreeSet 高频易错点存入自定义对象没有指定排序规则 → 抛出ClassCastException判定重复不靠 equals比较方法返回 0 就直接去重这点和 HashSet 完全不同非常容易混淆不能存入 null会空指针HashSet 可以存一个 null排序不是 “存取顺序”是数值、属性的大小顺序不要和 LinkedHashSet 的有序搞混比较器 Comparator 支持 Lambda因为是函数式接口符合之前 Lambda 的知识点红黑树是平衡二叉树保证查询、增删时间复杂度 O (logn)不会退化成链表六、选择使用场景只需要去重、不在乎顺序优先 HashSet需要去重同时保留添加顺序LinkedHashSet需要去重并且自动按属性大小排序TreeSet七、速记口诀TreeSet 红黑树排序去重两不误 Comparable 自然排实体类里重写 compareTo Comparator 比较器构造传入更灵活 返回零值就去重和 Hash 规则不一样 空值不能往里放优先比较器来做主。