treeset底层基于treemap实现,而treemap使用自平衡红黑树,排序依赖元素的comparable接口或comparator;插入时通过compareto或compare决定左右子树走向,中序遍历天然有序,时间复杂度为o(log n)。

TreeSet 底层基于 TreeMap 实现,而 TreeMap 的核心是红黑树(Red-Black Tree)。它本身不直接排序元素,而是依赖元素的 自然顺序(即实现 Comparable 接口并重写 compareTo())或外部传入的 Comparator 来决定插入位置和遍历顺序。
自然排序靠 compareTo() 决定节点走向
当你用无参构造创建 TreeSet(如 new TreeSet()),它内部会使用默认的 TreeMap,该 TreeMap 要求键(即 TreeSet 中的元素)必须实现 Comparable。每次添加元素时:
- 红黑树从根节点开始,反复调用
e1.compareTo(e2)比较大小 - 若返回负数 → 当前元素小于比较对象 → 向左子树查找
- 若返回正数 → 当前元素大于比较对象 → 向右子树查找
- 若返回 0 → 认为元素重复,不插入(TreeSet 不允许重复)
红黑树只保证结构平衡,不负责定义“大小”
红黑树本身是一套自平衡二叉搜索树规则(颜色标记、旋转、变色等),它不关心“谁大谁小”,只严格遵守:
– 左子树所有节点 ≤ 当前节点
– 右子树所有节点 ≥ 当前节点
这个“≤”和“≥”的语义,完全由 compareTo() 的返回值解释。也就是说:
- 红黑树提供插入/删除/查找的高效结构(O(log n))
- 排序逻辑完全解耦,交由元素自身或 Comparator 承担
- 哪怕你把 String 按长度比较、把 Person 按年龄倒序,只要
compareTo()返回合理结果,TreeSet 就能正确排序和去重
注意 null 和类型一致性
使用自然排序时容易出错的点:
- 存入
null:抛NullPointerException(因为null.compareTo(...)会空指针) - 混入不同类型的对象(如同时 add("abc") 和 add(123)):抛
ClassCastException(运行时强转失败) -
compareTo()实现违反自反性、传递性、对称性:可能导致查找失败或结构异常(比如两个不相等对象 compare 返回 0)
底层实际是 TreeMap 的 key 集合视图
TreeSet 的源码里几乎全是调用 map.put(e, PRESENT)(PRESENT 是个空 static 对象),它的迭代器也直接遍历 TreeMap 的 keySet。所以:
- TreeSet 的“有序”本质就是 TreeMap 的中序遍历结果(左→根→右)
- 中序遍历红黑树天然得到升序序列(按 compareTo 定义的顺序)
- 没有额外排序过程,插入时位置已由比较结果+红黑树调整策略确定
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











