TreeSet适合需自动排序、去重且不关心插入顺序的场景,基于红黑树实现,支持自然排序或自定义比较器,时间复杂度O(log n),提供范围查询、边界获取及逆序视图等功能。

TreeSet适合需要自动排序、去重,且不关心插入顺序的场景。它底层基于红黑树实现,天然支持元素的自然排序(或按指定比较器排序),同时保证唯一性,但不支持null元素,也不允许在运行时修改影响排序的字段。
需要自动维持升序/降序的集合
当你每次添加元素后都希望集合保持有序,比如维护一个实时排名榜单、时间戳队列、或价格区间列表,TreeSet能省去手动排序和去重的代码。它在add/remove操作中自动调整结构,时间复杂度稳定在O(log n)。
- 适合替代“先add进ArrayList再Collections.sort() + 去重”的低效做法
- 调用first()、last()、higher()、lower()等方法可快速获取边界值或邻近元素
- 使用descendingSet()可直接获得逆序视图,无需重建集合
频繁执行范围查询或区间操作
TreeSet提供了subSet()、headSet()、tailSet()等方法,能高效截取某段范围内的元素。例如:找出所有价格在100~500之间的商品,或获取最近7天的订单时间点。
- subSet(fromElement, toElement)返回左闭右开区间的视图(注意:fromElement必须≤toElement,且均需存在于自然序中)
- 这些子集是原集合的“实时视图”,修改子集会同步影响原TreeSet
- 比遍历整个集合做if判断快得多,尤其在大数据量下优势明显
元素本身具备明确大小关系
TreeSet要求元素可比较。要么实现Comparable接口(如String、Integer、LocalDateTime默认已实现),要么构造时传入Comparator。如果业务对象没有天然顺序(比如User类),需主动定义排序逻辑。
- 推荐用Lambda写简洁比较器:new TreeSet((a, b) -> a.getScore() - b.getScore())
- 避免在比较逻辑中引用可能为null的字段,否则运行时抛NullPointerException
- 若比较结果依赖可变字段(如obj.setName("new")后再次插入同一对象),会导致行为异常——应确保用于比较的字段不可变或插入后不再修改
不需要随机访问或按索引查元素
TreeSet不提供get(int index)或类似List的操作。它本质是SortedSet,定位靠比较而非位置。如果代码里常写“第3个元素”“倒数第2个”,说明它不是最佳选择。
- 想按位置访问?考虑先转成ArrayList:new ArrayList(treeSet).get(2)
- 但要注意:转列表会丢失O(log n)优势,仅适合偶尔查、数据量不大时
- 高频索引访问+排序需求,可考虑TreeMap配合维护索引,或用专门库如Apache Commons Collections的 TreeList










