【某大厂一面】HashSet底层怎么实现的

news2025/1/30 19:33:39

HashSet 是 Java 集合框架中的一个非常常用的集合类,它实现了 Set 接口,并且底层通常是通过 哈希表HashMap)来实现的。要理解 HashSet 的底层实现,我们需要从哈希表的工作原理开始讲起。下面是对 HashSet 底层实现的详细解析。

1. HashSet 的基本特性

  • 无重复元素HashSet 不允许存储重复的元素。如果向 HashSet 中添加一个已经存在的元素,插入操作会失败。
  • 不保证元素的顺序HashSet 不保证元素的顺序,它会根据元素的哈希值决定元素存储的顺序。
  • 支持 null 元素HashSet 允许存储一个 null 元素。

2. HashSet 底层实现原理

HashSet 实际上是基于 哈希表 实现的,而哈希表的实现是通过 HashMap 类来完成的。其基本结构和工作原理如下:

  • HashSet 使用了 HashMap 作为底层存储结构。
  • 每个 HashSet 中的元素都会作为 HashMapkey 存储,而 HashMapvalue 部分则始终使用一个固定的对象(通常是 Object)作为占位符。
哈希表(HashMap)工作原理:
  1. 哈希值计算:当元素被插入到 HashSet 中时,首先会计算该元素的哈希值(使用元素的 hashCode() 方法)。哈希值决定了元素应该存放在哈希表的哪个位置。
  2. 冲突处理:如果两个不同的元素有相同的哈希值(即哈希冲突),HashMap 会通过链表(在 Java 8 之后,也可能是红黑树)来处理这些冲突。链表或树结构会存储多个哈希值相同的元素。
  3. 键值存储:在 HashMap 中,每个 key 对应着一个值(value)。在 HashSet 中,value 部分是固定的,通常不关心具体的值。
HashSet 依赖 HashMap 的特点:
  • 插入操作时,HashSet 会调用 HashMap.put(key, value) 方法来将元素作为 key 存储。
  • 查找操作时,HashSet 会调用 HashMap.containsKey(key) 方法来判断该元素是否存在。
  • 删除操作时,HashSet 会调用 HashMap.remove(key) 方法来删除元素。

3. HashSet 的常用操作分析

1. 添加元素(add()

当调用 HashSetadd() 方法时,底层实际上调用的是 HashMapput() 方法:

  • 计算元素的哈希值。
  • 判断该元素是否已经存在于哈希表中(即是否有相同的哈希值且相等的元素)。
  • 如果元素不存在,插入元素并返回 true;如果元素已经存在,返回 false
public boolean add(E e) {
    return map.put(e, PRESENT) == null; // map.put() 返回值为 null 表示插入成功
}

HashSet 中,PRESENT 是一个常量,通常是 new Object()

2. 查找元素(contains()

查找操作会调用 HashMapcontainsKey() 方法:

  • 计算元素的哈希值。
  • 判断该哈希值对应的桶中是否存在元素。
  • 如果存在,进一步比较元素是否相等(使用 equals() 方法),如果相等返回 true,否则返回 false
public boolean contains(Object o) {
    return map.containsKey(o); // 调用 HashMap 的 containsKey()
}
3. 删除元素(remove()

删除操作会调用 HashMapremove() 方法:

  • 计算元素的哈希值。
  • 查找该元素并删除。
public boolean remove(Object o) {
    return map.remove(o) == PRESENT; // 调用 HashMap 的 remove() 删除元素
}
4. 获取集合大小(size()

返回 HashSet 中存储的元素数量,底层是通过 HashMapsize() 方法获取的:

public int size() {
    return map.size(); // 调用 HashMap 的 size() 获取大小
}

4. HashSetHashMap 的关系

  • HashSet 本质上是对 HashMap 的包装,HashSet 的元素会作为 HashMapkey 存储,而 value 部分固定不变。
  • HashMapkey 使用 hashCode()equals() 方法来判断元素是否相等,所以 HashSet 中的元素也必须重写 hashCode()equals() 方法。
  • HashSet 具有与 HashMap 相同的效率特性,所有常用操作(插入、查找、删除)的时间复杂度均为 O(1),但在最坏情况下(哈希冲突严重)为 O(n)。

5. HashSet 性能特点

由于 HashSet 底层是基于哈希表的,因此它在大多数情况下提供非常高效的性能:

  • 插入操作:O(1),在没有哈希冲突的情况下,插入一个元素是常数时间。
  • 查找操作:O(1),由于哈希表是基于哈希值查找元素,查找操作通常是常数时间。
  • 删除操作:O(1),与查找操作类似,删除操作也基于哈希值进行快速定位。
  • 最坏情况下:如果所有元素都发生哈希冲突(即所有元素都被分配到同一个桶中),则所有操作的时间复杂度会退化到 O(n)。

为了减少哈希冲突,HashSetHashMap 都采用了动态扩容和哈希重哈希机制。当哈希表的负载因子(实际存储的元素数与数组容量之比)超过某个阈值时,会进行扩容(通常会将数组大小扩展为原来的 2 倍),并重新计算所有元素的哈希值并重新分配到新的数组位置。

6. HashSet 的扩容机制

HashSet 会根据负载因子和容量来动态调整内部存储数组的大小。默认情况下,HashSet 的初始容量为 16,负载因子为 0.75。

  • 容量:是哈希表的数组大小。
  • 负载因子:是哈希表的填充程度,默认值为 0.75。当哈希表中存储的元素个数超过容量的 75% 时,哈希表会进行扩容。

扩容操作会导致重新计算所有元素的哈希值,因此在性能方面可能会有一定的开销。

7. 总结

特性HashSet
底层实现基于 HashMap
是否允许重复元素不允许
是否保证顺序不保证
存储元素的方式元素作为 HashMapkey 存储,value 固定
插入操作时间复杂度O(1),最坏情况 O(n)
查找操作时间复杂度O(1),最坏情况 O(n)
删除操作时间复杂度O(1),最坏情况 O(n)

HashSet 是一个高效的集合类,适用于需要去重、无序存储的场景。它的性能与哈希表的设计紧密相关,能够提供快速的插入、查找和删除操作。

小伙伴们在开发过程中有使用心得可以再评论区一块讨论哦

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2286568.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网关登录校验

网关登录校验 单体架构时我们只需要完成一次用户登录、身份校验,就可以在所有业务中获取到用户信息。而微服务拆分后,每个微服务都独立部署,不再共享数据。也就意味着每个微服务都需要做登录校验,这显然不可取。 鉴权思路分析 …

【C语言】在Windows上为可执行文件.exe添加自定义图标

本文详细介绍了在 Windows 环境下,如何为使用 GCC 编译器编译的 C程序 添加自定义图标,从而生成带有图标的 .exe 可执行文件。通过本文的指导,读者可以了解到所需的条件以及具体的操作步骤,使生成的程序更具专业性和个性化。 目录 1. 准备条件2. 具体步骤步骤 1: 准备资源文…

计算机毕业设计Python+知识图谱大模型AI医疗问答系统 健康膳食推荐系统 食谱推荐系统 医疗大数据 机器学习 深度学习 人工智能 爬虫 大数据毕业设计

温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…

商品信息管理自动化测试

目录 前言 一、思维导图 二、代码编写 1.在pom.xml文件中添加相关依赖 2.自动化代码编写 三、代码测试 小结 前言 1. 针对商品信息管理项目进行测试,商品信息管理项目主要有商品列表页、部门列表页、员工列表页,主要功能:对商品信息的…

【实践】基于SakuraLLM的离线日文漫画及视频汉化

介绍 LLM 大型语言模型(英语:large language model,LLM),也称大语言模型,是由具有大量参数(通常数十亿个权重或更多)的人工神经网络组成的一类语言模型。在进行语言理解与分析&…

常见的同态加密算法收集

随着对crypten与密码学的了解,我们将逐渐深入学习相关知识。今天,我们将跟随同态加密的发展历程对相关算法进行简单的收集整理 。 目录 同态加密概念 RSA算法 ElGamal算法 ELGamal签名算法 Paillier算法 BGN方案 Gentry 方案 BGV 方案 BFV 方案…

SSM-MyBatis-总结

文章目录 一、Hello MyBatis1.1 流程1.2 总结 二、Crud 的一些注意点三、参数传递3.1 #{ } VS ${ }3.2 单、复参数传递(1)单参数(2)多参数 -- Param(3)总结 四、查询结果返回--结果封装4.1 ResultType 一般…

万字长文总结前端开发知识---JavaScriptVue3Axios

JavaScript学习目录 一、JavaScript1. 引入方式1.1 内部脚本 (Inline Script)1.2 外部脚本 (External Script) 2. 基础语法2.1 声明变量2.2 声明常量2.3 输出信息 3. 数据类型3.1 基本数据类型3.2 模板字符串 4. 函数4.1 具名函数 (Named Function)4.2 匿名函数 (Anonymous Fun…

Flutter android debug 编译报错问题。插件编译报错

下面相关内容 都以 Mac 电脑为例子。 一、问题 起因:(更新 Android studio 2024.2.2.13、 Flutter SDK 3.27.2) 最近 2025年 1 月 左右,我更新了 Android studio 和 Flutter SDK 再运行就会出现下面的问题。当然 下面的提示只是其…

【Proteus仿真】【51单片机】简易计算器系统设计

目录 一、主要功能 二、使用步骤 三、硬件资源 四、软件设计 五、实验现象 联系作者 一、主要功能 1、LCD1602液晶显示 2、矩阵按键​ 3、可以进行简单的加减乘除运算 4、最大 9999*9999 二、使用步骤 系统运行后,LCD1602显示数据,通过矩阵按键…

JavaScript函数中this的指向

总结:谁调用我,我就指向谁(es6箭头函数不算) 一、ES6之前 每一个函数内部都有一个关键字是 this ,可以直接使用 重点: 函数内部的 this 只和函数的调用方式有关系,和函数的定义方式没有关系 …

51单片机入门_01_单片机(MCU)概述(使用STC89C52芯片;使用到的硬件及课程安排)

文章目录 1. 什么是单片机1.1 微型计算机的组成1.2 微型计算机的应用形态1.3 单板微型计算机1.4 单片机(MCU)1.4.1 单片机内部结构1.4.2 单片机应用系统的组成 1.5 80C51单片机系列1.5.1 STC公司的51单片机1.5.1 STC公司单片机的命名规则 2. 单片机的特点及应用领域2.1 单片机的…

51单片机入门_02_C语言基础0102

C语言基础部分可以参考我之前写的专栏C语言基础入门48篇 以及《从入门到就业C全栈班》中的C语言部分,本篇将会结合51单片机讲差异部分。 课程主要按照以下目录进行介绍。 文章目录 1. 进制转换2. C语言简介3. C语言中基本数据类型4. 标识符与关键字5. 变量与常量6.…

时间轮:XXL-JOB 高效、精准定时任务调度实现思路分析

大家好,我是此林。 定时任务是我们项目中经常会遇到的一个场景。那么如果让我们手动来实现一个定时任务框架,我们会怎么做呢? 1. 基础实现:简单的线程池时间轮询 最直接的方式是创建一个定时任务线程池,用户每提交一…

人工智能如何驱动SEO关键词优化策略的转型与效果提升

内容概要 随着数字化时代的到来,人工智能(AI)技术对各行各业的影响日益显著,在搜索引擎优化(SEO)领域尤为如此。AI的应用不仅改变了关键词研究的方法,而且提升了内容生成和搜索优化的效率&…

【NLP251】NLP RNN 系列网络

NLP251 系列主要记录从NLP基础网络结构到知识图谱的学习 1.原理及网络结构 1.1RNN 在Yoshua Bengio论文中( http://proceedings.mlr.press/v28/pascanu13.pdf )证明了梯度求导的一部分环节是一个指数模型…

【越学学糊涂的Linux系统】Linux指令篇(二)

一、pwd指令: 00x0:打印该用户当前目录下所属的文件路径 看指令框可以看出我用的是一个叫sw的用户,我们的路径就是在一个home目录下的sw目录下的class113文件路径。 也可以说是指出当前所处的工作目录 补充:🎆​​​​​​​Wi…

【AI论文】Omni-RGPT:通过标记令牌统一图像和视频的区域级理解

摘要:我们提出了Omni-RGPT,这是一个多模态大型语言模型,旨在促进图像和视频的区域级理解。为了在时空维度上实现一致的区域表示,我们引入了Token Mark,这是一组在视觉特征空间中突出目标区域的标记。这些标记通过使用区…

Java面试题2025-并发编程基础(多线程、锁、阻塞队列)

并发编程 一、线程的基础概念 一、基础概念 1.1 进程与线程A 什么是进程? 进程是指运行中的程序。 比如我们使用钉钉,浏览器,需要启动这个程序,操作系统会给这个程序分配一定的资源(占用内存资源)。 …

Three城市引擎地图插件Geo-3d

一、简介 基于Three开发,为Three 3D场景提供GIS能力和城市底座渲染能力。支持Web墨卡托、WGS84、GCJ02等坐标系,支持坐标转换,支持影像、地形、geojson建筑、道路,植被等渲染。支持自定义主题。 二、效果 三、代码 //插件初始化…