TreeSet底层基于红黑树实现,通过Comparable接口或Comparator定制排序,插入/删除后通过变色与旋转维持平衡,确保O(log n)时间复杂度及稳定排序。

TreeSet 底层基于 TreeMap 实现,而 TreeMap 的核心是红黑树(Red-Black Tree)。它本身不直接存储元素,而是把元素作为 key 存入 TreeMap,value 固定为一个共享的空对象(PRESENT)。所以 TreeSet 的排序行为完全由 TreeMap 的插入和查找逻辑决定。
自然排序:依赖元素实现 Comparable 接口
当创建无参 TreeSet(new TreeSet())时,TreeMap 使用默认比较器 —— 即要求所有添加的元素必须实现 Comparable 接口,并重写 compareTo() 方法。红黑树在插入节点时,会反复调用该方法比较大小,决定左子树还是右子树方向。
- 例如:
TreeSet<integer></integer>能正常工作,因为Integer实现了Comparable<integer></integer>,compareTo()按数值升序比较 - 若自定义类(如
Person)未实现Comparable,直接加入无参 TreeSet 会抛ClassCastException
定制排序:传入 Comparator 实现类或 Lambda
通过带 Comparator 参数的构造器(new TreeSet(comparator)),TreeMap 在比较节点时改用你提供的比较逻辑,不再强求元素自身可比较。
- 可以传匿名内部类、方法引用,或更简洁的 Lambda 表达式,比如:
new TreeSet((a, b) -> b.compareTo(a))实现降序 - Comparator 的
compare(a, b)返回负数、0、正数,分别表示 a 小于、等于、大于 b;红黑树据此调整节点位置并维持平衡 - 即使元素类没实现
Comparable,只要 comparator 能处理,就能放进 TreeSet
红黑树如何在排序基础上维持平衡
排序只解决“放哪”,平衡才保障性能。TreeMap 的红黑树在每次插入/删除后,通过 变色 + 旋转(左旋、右旋)来恢复红黑树五条性质,尤其是“从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点”这一条。
立即学习“Java免费学习笔记(深入)”;
- 插入新节点默认为红色,可能违反“不能有两个连续红节点”的规则,于是触发 recolor 或 rotation
- 旋转不改变中序遍历顺序,因此不影响已有的排序结果 —— 这是关键:**结构变化但逻辑顺序不变**
- 所有操作(add/remove/contains)时间复杂度稳定在 O(log n),前提是 compare/compareTo 实现正确且不抛异常
注意:排序依据必须稳定且符合合同
无论用自然排序还是定制排序,比较逻辑必须满足:自反性、对称性、传递性、一致性。否则红黑树行为不可预测,可能出现重复元素未去重、contains() 返回 false、甚至死循环。
- 避免在
compareTo()或compare()中使用随机数、当前时间、外部状态等易变值 - 如果比较依赖对象字段,确保这些字段在加入 TreeSet 后不再修改(否则视图错乱,但 TreeSet 不做防护)
- 对于 null 值:自然排序中 null 通常抛 NPE;定制排序中可主动处理,比如把 null 视为最小或最大


















