优先选 HashSet 实现快速去重,平均 O(1) 时间复杂度,适合高频判重;需自动排序或范围查询则选 TreeSet,基于红黑树实现 O(log n) 操作,支持 first()/last() 和 subSet 等功能。

选 HashSet 还是 TreeSet,关键看你要不要排序,以及对性能有没有硬性要求。
需要快速去重,不关心顺序?用 HashSet
它底层是哈希表(实际复用 HashMap),add、remove、contains 都是平均 O(1) 时间复杂度。插入和查询极快,适合高频判重场景,比如:
- 过滤重复请求 ID 或用户行为日志
- 缓存中快速判断某个 key 是否已存在
- 大批量数据临时去重后转成 List 处理
注意:它不保证任何顺序,遍历结果可能每次都不一样;允许存一个 null;自定义对象必须正确重写 hashCode() 和 equals(),否则去重失效。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
需要元素自动有序,或做范围操作?用 TreeSet
它底层是红黑树(复用 TreeMap),所有元素按自然顺序(如数字升序、字符串字典序)或你传入的 Comparator 排好,add/remove/contains 是稳定 O(log n)。适用场景包括:
- 实时维护一个有序排行榜(如 Top 10 分数)
- 需要 subSet、headSet、tailSet 等范围查询
- 频繁取最小值(first())、最大值(last())
注意:不能存 null(比较时会抛 NullPointerException);插入比 HashSet 慢,尤其数据量大时;排序依赖 compareTo() 或 compare(),不是靠 equals。
其他现实考量
如果只是偶尔排序,但主要操作是增删查,别为了“最后排个序”就选 TreeSet——先用 HashSet 处理完,再转成 List 排序更高效。
- 已有 List 要去重+排序:new TreeSet(list) 一行搞定,但仅限小数据量
- 要保持插入顺序:HashSet 不行,得换 LinkedHashSet
- 并发环境:两者都不线程安全,高并发下需用 Collections.synchronizedSet() 或 CopyOnWriteArraySet

















