【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()方法)
    • 元素具有自然顺序或需要自定义排序规则
相关推荐
foundbug9998 小时前
自适应滤除直达波干扰的MATLAB实现
开发语言·算法·matlab
XDH_CS8 小时前
MySQL 8.0 安装与 MySQL Workbench 使用全流程(超详细教程)
开发语言·数据库·mysql
小短腿的代码世界8 小时前
Qt实时盈亏计算深度解析:从持仓数据到动态盈亏展示
开发语言·qt
小康小小涵9 小时前
基于ESP32S3实现无人机RID模块底层源码编译
linux·开发语言·python
lzjava20249 小时前
Python的函数
开发语言·python
掌心向暖RPA自动化9 小时前
如何获取网页某个元素在屏幕可见部分的中心坐标影刀RPA懒加载坐标定位技巧
java·javascript·自动化·rpa·影刀rpa
Awesome Baron9 小时前
skill、tool calling、MCP区别
开发语言·人工智能·python
日取其半万世不竭9 小时前
Minecraft Java版社区服务器搭建教程(Linux,适合新手)
java·linux·服务器
Python私教9 小时前
GenericAgent PySide6 桌面应用深度解析:悬浮按钮 + 聊天面板的原生 Qt 方案
开发语言·数据库·qt
矢志航天的阿洪9 小时前
用 MATLAB 控制 STK Aviator:从零搭建一个 AWACS 支援作战场景
开发语言·matlab