treeset底层基于红黑树,通过封装treemap实现,元素作为key、present为value;要求元素可比较,否则抛classcastexception;不存null(默认比较器下),自动去重,遍历严格有序。

TreeSet底层确实是红黑树,但不是直接用java.util.TreeMap的实例
TreeSet内部封装了一个TreeMap,所有元素作为TreeMap的key存储,value统一是PRESENT(一个静态的Object哨兵对象)。所以TreeSet的排序行为完全由TreeMap保证——而TreeMap在JDK中就是基于红黑树实现的有序映射。
这意味着:TreeSet不维护独立的树结构,它只是TreeMap的“key视图”。插入、删除、查找的时间复杂度都是O(log n),稳定性依赖红黑树的自平衡机制。
自动排序的前提是元素必须可比较
TreeSet要求存入的元素满足以下任一条件,否则运行时抛出ClassCastException:
- 元素类型实现了
Comparable接口,且compareTo()方法定义了合理全序关系 - 构造TreeSet时显式传入
Comparator,比如new TreeSet(Comparator.comparingInt(String::length))
常见翻车点:new TreeSet<string>()</string>能用,是因为String实现了Comparable;但new TreeSet<stringbuilder>()</stringbuilder>会直接抛异常——StringBuilder没实现Comparable,也没给Comparator。
立即学习“Java免费学习笔记(深入)”;
红黑树特性决定了TreeSet的行为边界
红黑树是自平衡二叉搜索树,这带来几个关键约束:
- 重复元素被静默丢弃:因为底层是
TreeMap.put(key, value),相同key会覆盖,TreeSet表现为“去重” - 不能存
null(除非用自定义Comparator且明确支持null):默认比较器对null调用compareTo()会NPE - 遍历结果严格按比较规则升序(或
Comparator定义的顺序),但不保证插入顺序 - 不支持随机访问,没有
get(int index)这类操作
例如:TreeSet<integer> set = new TreeSet(Collections.reverseOrder());</integer> —— 这里用的是Comparator反转,底层红黑树仍按新规则建树,不是“把升序结果再倒过来”。
别把TreeSet和SortedSet接口混淆
SortedSet只是规范“有序集合”的行为(如first()、headSet()),不规定实现方式。TreeSet是它的标准实现,但其他类也可以实现SortedSet(比如用数组+插入排序模拟,虽然没人真这么干)。真正提供排序能力的是TreeSet背后的红黑树逻辑,不是接口本身。
如果你看到某些场景下TreeSet排序“失效”,先检查compareTo()是否违反自反性(比如a.compareTo(a) != 0)或传递性——红黑树依赖这些数学性质维持结构,一旦破坏,行为不可预测,甚至可能死循环。









