在 Java 集合框架中TreeSet是基于红黑树实现的有序、不重复集合它不仅能保证元素无重复还能按照指定规则对元素进行排序是处理有序唯一元素场景的核心工具。一、TreeSet 基础定义TreeSet是java.util包下的实现类核心特性元素唯一性不允许存储重复元素通过比较器判断重复而非 equals 方法有序性元素会按照自然排序如 Integer 升序、String 字典序或自定义排序规则排列非线程安全多线程并发操作时需手动加锁或使用Collections.synchronizedSortedSet包装不允许 null 元素JDK 8 及以后TreeSet 存储 null 会抛出NullPointerException排序时无法比较 null底层数据结构红黑树自平衡二叉查找树保证增删改查的时间复杂度为 O(logn)。二、TreeSet 继承与实现关系TreeSet 的继承体系清晰体现了其功能定位完整层级关系如下java.lang.Object ↳ java.util.AbstractCollectionE ↳ java.util.AbstractSetE ↳ java.util.TreeSetE核心接口实现NavigableSetE提供导航性方法如获取小于 / 大于某个元素的节点、逆序遍历等SortedSetE保证集合元素有序支持获取子集、首尾元素等有序操作Cloneable支持克隆Serializable支持序列化。简化理解TreeSet 有序 无重复 导航功能的集合所有有序特性依赖NavigableSet和SortedSet接口。三、TreeSet 源码深度解析JDK 8TreeSet 是装饰者模式的典型应用底层没有自己的数据结构完全基于TreeMap实现所有核心操作都委托给 TreeMap。这是理解 TreeSet 源码的核心突破口。1. 核心成员变量public class TreeSetE extends AbstractSetE implements NavigableSetE, Cloneable, java.io.Serializable { // 底层存储TreeSet 的所有元素都存在 TreeMap 的 key 中 private transient NavigableMapE,Object m; // 固定的默认值TreeMap 的 value 是无意义的占位符所有元素共享此对象 private static final Object PRESENT new Object(); // 序列化版本号 private static final long serialVersionUID -2479143000642829578L; }结论TreeSet 本质是TreeMap 的 key 集合value 统一为PRESENT静态对象TreeMap 底层是红黑树因此 TreeSet 天然继承了红黑树的有序、自平衡特性。2. 核心构造方法TreeSet 提供 5 种构造方法核心都是初始化底层的 TreeMap// 1. 无参构造使用自然排序底层创建 TreeMap public TreeSet() { this(new TreeMapE,Object()); } // 2. 带比较器构造自定义排序规则 public TreeSet(Comparator? super E comparator) { this(new TreeMap(comparator)); } // 3. 集合参数构造将指定集合转为 TreeSet自然排序 public TreeSet(Collection? extends E c) { this(); addAll(c); } // 4. SortedSet参数构造复用已有排序规则 public TreeSet(SortedSetE s) { this(s.comparator()); addAll(s); } // 5. 包访问权限构造直接传入 NavigableMap供内部使用 TreeSet(NavigableMapE,Object m) { this.m m; }核心逻辑所有构造方法最终都是为了初始化底层的NavigableMap实际为 TreeMap。3. 核心增删改查方法TreeSet 的所有方法都是调用 TreeMap 的对应方法源码极其简洁1add (E e)添加元素public boolean add(E e) { // 调用 TreeMap 的 put 方法key元素value固定的 PRESENT return m.put(e, PRESENT) null; }原理TreeMap 的 put 会将元素插入红黑树并自动平衡树结构若元素已存在比较器判定重复put 返回旧值add 返回 false保证元素唯一若元素不存在put 返回 nulladd 返回 true插入成功。2remove (Object o)删除元素public boolean remove(Object o) { // 调用 TreeMap 的 remove 方法返回旧值 return m.remove(o) PRESENT; }原理删除红黑树中的节点自动调整树平衡若元素存在删除成功返回 true否则返回 false。3contains (Object o)判断元素是否存在public boolean contains(Object o) { // 调用 TreeMap 的 containsKey return m.containsKey(o); }4size()/isEmpty()/clear()public int size() { return m.size(); } public boolean isEmpty() { return m.isEmpty(); } public void clear() { m.clear(); }全部委托 TreeMap 实现无任何自定义逻辑。4. 排序核心比较器TreeSet 判断元素是否重复和排序规则完全依赖比较器而非 equals/hashCode自然排序元素实现Comparable接口重写compareTo方法如 Integer、String 默认实现自定义排序创建 TreeSet 时传入Comparator接口实现重写compare方法。源码关联TreeMap 的 put/get 操作会调用比较器的 compare 方法若返回 0判定为重复元素。四、TreeSet 内部方法有序 / 导航方法作为NavigableSet实现类TreeSet 提供了大量有序导航方法这是 HashSet 不具备的核心能力first()获取集合第一个元素最小元素last()获取集合最后一个元素最大元素lower(E e)获取小于 e 的最大元素higher(E e)获取大于 e 的最小元素floor(E e)获取小于等于 e 的最大元素ceiling(E e)获取大于等于 e 的最小元素subSet(E from, boolean fromInclusive, E to, boolean toInclusive)获取指定范围的子集headSet(E to, boolean inclusive)获取小于 to 的子集tailSet(E from, boolean inclusive)获取大于 from 的子集。这些方法底层均调用 TreeMap 的对应导航方法时间复杂度 O(logn)。五、TreeSet 迭代器实现TreeSet 的迭代器基于红黑树的中序遍历实现保证遍历顺序与排序顺序一致。1. 获取迭代器public IteratorE iterator() { // 调用 TreeMap 的 keySet 迭代器 return m.navigableKeySet().iterator(); }2. 迭代器特性有序遍历中序遍历红黑树输出升序排序结果自然排序 / 自定义排序快速失败Fail-Fast迭代过程中若修改集合add/remove会抛出ConcurrentModificationException支持逆序迭代通过descendingIterator()获取逆序迭代器遍历降序元素。核心原理红黑树的中序遍历规则 左子树 → 根节点 → 右子树天然保证有序输出。六、TreeSet 与 HashSet 核心对比两者都是 Set 接口实现类核心区别源于底层数据结构详细对比特性TreeSetHashSet底层结构红黑树哈希表数组 链表 红黑树元素顺序有序自然 / 自定义排序无序JDK 8 后遍历顺序固定但无排序意义重复判断比较器compare/compareTo 返回 0equals() hashCode()元素要求必须实现 Comparable / 传入比较器无强制要求建议重写 equals/hashCode时间复杂度增删改查O(logn)增删改查O(1)哈希冲突少null 元素不允许允许存储 1 个 null性能较低红黑树自平衡开销较高哈希寻址效率高适用场景需排序、去重的有序场景仅需去重、追求高性能场景一句话总结需要有序选 TreeSet追求性能选 HashSet。七、TreeSet 面试高频知识点1. TreeSet 如何保证元素有序底层基于红黑树实现插入元素时通过比较器Comparable/Comparator确定元素在红黑树中的位置迭代时通过中序遍历红黑树保证输出有序。2. TreeSet 如何判断元素重复不是通过 equals 方法而是通过比较器的compareTo或compare方法若返回 0判定为重复元素拒绝插入。3. 为什么 TreeSet 不允许存储 nullTreeSet 插入元素时会调用比较器进行排序null 无法参与比较JDK 8 及以后会直接抛出NullPointerException。4. TreeSet 与 TreeMap 的关系TreeSet 是 TreeMap 的包装类TreeSet 所有元素存储在 TreeMap 的 key 中value 为固定静态对象所有核心操作委托 TreeMap 实现。5. TreeSet 迭代时为什么会报并发修改异常TreeSet 迭代器采用快速失败机制迭代过程中会检测modCount修改次数若集合被修改modCount变化立即抛出异常避免遍历数据不一致。6. 自然排序 vs 自定义排序优先级自定义排序Comparator优先级高于自然排序Comparable若创建 TreeSet 时传入 Comparator优先使用自定义比较器否则使用元素的 Comparable 接口。7. TreeSet 是线程安全的吗不是。多线程环境下推荐使用java.util.concurrent.ConcurrentSkipListSet线程安全的有序集合或用Collections.synchronizedSortedSet包装。八、总结TreeSet 是基于 TreeMap红黑树实现的有序、无重复集合核心是红黑树的自平衡和排序特性所有操作委托 TreeMap 实现判断重复依赖比较器而非 equals/hashCode适合需要排序 去重的场景性能低于 HashSet但具备强大的有序导航能力面试核心考点底层结构、重复判断、排序规则、与 HashSet/TreeMap 的区别、并发安全。掌握 TreeSet 的核心本质是掌握红黑树和比较器的原理这也是理解 Java 有序集合的关键。