TreeSet 通过红黑树实现自动排序,要求元素可比较(Comparable 或 Comparator),不允许多个 null 或不可比类型,插入为 O(log n) 并自动平衡,重复元素被忽略,遍历天然有序,适用于需排序、范围查询场景。

TreeSet 在 Java 中通过底层的红黑树(Red-Black Tree)结构实现元素的自动排序存储,它要求元素具备可比较性——要么实现 Comparable 接口,要么在构造时传入一个 Comparator 比较器。
TreeSet 依赖 Comparable 或 Comparator 判定顺序
TreeSet 不允许存储 null 元素(除非使用自定义 Comparator 显式允许),也不接受无法比较的类型。它在插入时调用元素自身的 compareTo() 方法(若实现了 Comparable),或委托给构造时传入的 Comparator.compare() 方法,据此决定节点在红黑树中的位置。
- 如果存的是 String、Integer 等 JDK 内置类型,它们已实现
Comparable,可直接使用默认升序 - 自定义类必须实现
Comparable并重写compareTo(),否则运行时报ClassCastException - 也可在创建 TreeSet 时传入 Lambda 或匿名 Comparator,例如:
new TreeSet((a, b) -> b.compareTo(a))实现降序
插入过程本质是红黑树的平衡插入
TreeSet 的 add() 操作不是简单遍历排序,而是基于红黑树的 O(log n) 插入:先按比较结果找到插入位置,再执行节点插入 + 自动旋转与着色调整,确保树始终满足红黑树性质(如任意路径黑节点数相同、无连续红节点等),从而维持有序性和查询效率。
- 重复元素会被忽略(TreeSet 不允许重复,依据 compare 返回 0 判定相等)
- 所有遍历操作(如 for-each、iterator)天然按排序顺序返回元素
- first()、last()、higher()、floor() 等方法都利用树结构快速定位,无需额外排序
注意自然排序与业务逻辑的一致性
排序依据是“比较逻辑”,不一定是业务意义上的“大小”。例如 Person 类按 age 排序,但两个 age 相同的 Person 若未在 compareTo() 中进一步比较 name 或 id,就会被当作重复元素丢弃。
立即学习“Java免费学习笔记(深入)”;
- 务必保证
compareTo()与equals()一致(即 a.compareTo(b) == 0 ⇔ a.equals(b)),否则可能违反 Set 合约 - 若业务需多字段组合排序,应在 compare 逻辑中逐级判断,避免仅靠单一字段
- 使用 Comparator 时同样要保证其满足自反性、对称性、传递性,否则 TreeSet 行为不可预测
与 HashSet、LinkedHashSet 的关键区别
TreeSet 牺牲了 O(1) 插入/查找的平均性能,换来了有序性与范围操作能力;而 HashSet 无序、不保证迭代顺序,LinkedHashSet 保持插入顺序但不支持排序。
- 需要按顺序遍历、找某范围内的元素(如
subSet(10, 20))、或获取极值时,TreeSet 更合适 - 只关心去重和快速存取,且不要求顺序,优先选 HashSet
- 想保留插入顺序又去重,用 LinkedHashSet


















