【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()方法)
    • 元素具有自然顺序或需要自定义排序规则
相关推荐
做人求其滴12 小时前
面试经典 150 题 380 274
c++·算法·面试·职场和发展·力扣
见叶之秋12 小时前
C++基础入门指南
开发语言·c++
小江的记录本12 小时前
【Java基础】Java 8-21新特性:JDK21 LTS:虚拟线程、模式匹配switch、结构化并发、序列集合(附《思维导图》+《面试高频考点清单》)
java·数据库·python·mysql·spring·面试·maven
daad77712 小时前
记一组无人机IMU传感器数据
算法
计算机安禾13 小时前
【c++面向对象编程】第42篇:模板特化与偏特化:为特定类型定制实现
开发语言·c++·算法
qq_4017004113 小时前
Qt 项目中使用 QSS 的全面总结
开发语言·qt
小O的算法实验室13 小时前
2026年KBS,流形感知强化学习差分进化算法+不规则3D无人机路径规划,深度解析+性能实测
算法·智能算法·智能算法改进
玖釉-13 小时前
C++ 中的循环语句详解:while、do...while、for、嵌套循环与循环控制
开发语言·c++·算法
XMYX-013 小时前
37 - Go env 环境变量:配置管理与运行时控制
开发语言·golang
不做无法实现的梦~13 小时前
运动控制系统复习一览-----常考题目总结版本
算法