【Java基础】- 集合-HashSet与TreeSet

一、底层实现与数据结构

类别 HashSet TreeSet
底层结构 哈希表(数组+链表+红黑树) • JDK8后链表长度≥8转为红黑树 • 通过hashCode()计算位置 红黑树(自平衡二叉搜索树) • 通过compareTo()或Comparator确定位置 • 不允许null元素
元素顺序 无序(随机) 有序(自然排序/自定义排序)
去重依据 hashCode() + equals() compareTo() 或 Comparator(比较结果为0即视为重复)
时间复杂度 O(1)(无冲突时) • 冲突时降为O(log n) O(log n) • 所有操作均为此复杂度
null支持 允许(仅1个) 不允许(抛出NullPointerException)
核心优势 • 极致性能的去重操作 • 高频插入/删除/查找 • 自动排序功能 • 支持范围查询(如subSet()) • 可获取最大/最小元素
典型场景 • 缓存系统 • 过滤重复数据 • 不关心顺序的集合 • 排行榜 • 按时间排序的任务队列 • 需范围查询的场景(如分数区间)
关键要求 • 必须重写hashCode()和equals() • 建议预设初始容量避免扩容 • 元素需实现Comparable或提供Comparator • 避免频繁结构修改
常见误区 • 未重写hashCode()导致去重失效 • 忽略负载因子导致频繁扩容 • 尝试存储null元素 • 误以为equals()决定去重(实际由比较器决定)
优化建议 • 设置合理初始容量(如new HashSet<>(1000)) • 确保hashCode()分布均匀 • 使用Comparator.nullsFirst()处理null • 批量操作用addAll()替代循环add()
线程安全方案 Collections.synchronizedSet() ConcurrentSkipListSet(替代品)

二、核心特性对比

特性 HashSet TreeSet
底层结构 哈希表(数组+链表+红黑树) 红黑树(自平衡二叉搜索树)
元素顺序 无序(随机) 有序(自然排序或自定义排序)
去重依据 hashCode() + equals() compareTo() 或 Comparator
null支持 允许(仅1个) 不允许(会抛出NPE)
时间复杂度 O(1)(无冲突) O(log n)
内存占用 较低 较高(需存储父节点、颜色标记等)
线程安全 否 否
特殊功能 无 范围查询、获取最大/最小元素等

三、TreeSet排序规则

排序方式 依据 规则 示例
自然排序(默认) 元素实现 Comparable<E> 接口的 compareTo(E o) 方法 - 返回负数:当前元素小,排在前面 - 返回 0:视为重复元素,不添加 - 返回正数:当前元素大,排在后面 - Integer:按数值大小升序 - String:按字典序升序 - 自定义对象需实现 Comparable 接口
定制排序 构造时传入 Comparator<? super E> 接口实现 - compare(o1, o2) 返回负数:o1 小于 o2,o1 排前 - 返回 0:视为重复,不添加 - 返回正数:o1 大于 o2,o2 排前 - 按字符串长度排序: (s1, s2) -> Integer.compare(s1.length(), s2.length()) - 按对象属性排序: (p1, p2) -> p1.getName().compareTo(p2.getName())
多级排序 使用 Comparator.thenComparing() 链式调用 - 先按主字段比较 - 主字段相等时,再按次字段比较 Comparator<Person> comp = Comparator.comparingInt(Person::getAge).thenComparing(Person::getName);
→ 先按年龄升序,年龄相同按姓名字典序
降序排序 使用 Comparator.reverseOrder() 或自定义比较逻辑 - 交换比较对象位置实现降序 - 或使用反向比较器 - 降序字符串: new TreeSet<>(Comparator.reverseOrder()) - 降序整数: (n1, n2) -> n2 - n1

四、性能特点详解

  1. HashSet性能
  • 优势:在无哈希冲突情况下,插入、删除、查找操作均达到O(1)时间复杂度
  • 瓶颈:哈希冲突时性能下降,链表长度>8时转为红黑树,性能变为O(log n)
  • 优化建议:
    • 预估数据量,设置合适的初始容量(避免扩容)
    • 合理设置负载因子(默认0.75)
    • 确保hashCode()分布均匀,减少冲突
  1. TreeSet性能
  • 优势:提供有序存储,支持范围查询(如查找大于某值的元素)
  • 瓶颈:所有操作时间复杂度为O(log n),比HashSet慢一个数量级
  • 优化建议:
    • 对于自定义对象,提供高效的Comparator
    • 避免频繁的结构修改(会触发树的重新平衡)
    • 大数据集下考虑使用NavigableSet接口提供的范围查询功能

五、适用场景与选择指南

  1. 优先选择HashSet的场景

    • 需要极致性能的去重操作
    • 不关心元素顺序,仅需判断元素是否存在
    • 高频的插入、删除、查找操作(如缓存系统、过滤重复数据)
    • 允许存储null元素的场景
  2. 优先选择TreeSet的场景

    • 需要自动排序的去重集合(如排行榜、按时间排序的任务队列)
    • 需要范围查询功能(如查找分数在80-90之间的学生)
    • 需要获取最大/最小元素(如first()、last()方法)
    • 元素具有自然顺序或需要自定义排序规则
相关推荐
Shaoshing几秒前
二分模板(左右查询)
java·算法·二分
小七在进步1 分钟前
C++内存管理:new/delete vs malloc/free深度解析
android·java·c++
yuniko-n3 分钟前
【JUC】公平锁与非公平锁
java
郑州光合科技余经理4 分钟前
本地生活服务系统:预约状态和进度通知接口怎么拆
java·开发语言·前端·javascript·后端·php·生活
靠沿8 分钟前
MySQL数据库基础——事务
java·数据库·mysql
AIFQuant8 分钟前
Python港股实时行情API接入:恒生股票数据获取与AH股溢价监控实战
开发语言·数据库·python·金融·实时数据api
蒲公英eric9 分钟前
线性回归与正则化:从最小二乘到岭回归、LASSO
人工智能·算法·数学建模·线性回归·岭回归·最小二乘·lasso
外收内放18 分钟前
Python基础语法练习题(70)
开发语言·python
碧海银沙音频科技研究院4 小时前
炬芯ATS3089X手表的HFP通话不自动路由到设备BT的问题解决
网络·人工智能·嵌入式硬件·算法