【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 小于 o2o1 排前 - 返回 0:视为重复,不添加 - 返回正数:o1 大于 o2o2 排前 - 按字符串长度排序: (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()方法)
    • 元素具有自然顺序或需要自定义排序规则
相关推荐
无尽的罚坐人生2 小时前
hot 100 73. 矩阵置零
线性代数·算法·矩阵
goodluckyaa2 小时前
thread block grid模型
算法
武帝为此2 小时前
【Rabbit加密算法介绍】
算法·安全
zhangzeyuaaa2 小时前
Python推导式(Comprehensions)
开发语言·python
m0_716765232 小时前
数据结构三要素、时间复杂度计算详解
开发语言·数据结构·c++·经验分享·笔记·算法·visual studio
卷心菜狗2 小时前
Python进阶基础--面向对象编程(OOP)
开发语言·python
开心码农1号2 小时前
RabbitMQ 生产运维命令大全
linux·开发语言·ruby
网安INF2 小时前
数据结构第二章复习:线性表
java·开发语言·数据结构
米粒12 小时前
力扣算法刷题 Day 36
算法·leetcode·职场和发展