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

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.mzph.cn/diannao/68553.shtml

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

相关文章

是否需要显式使用 epoll_ctl ( fd , EPOLL_CTL_DEL , ... ) 来从红黑树里显式删除过期的套接字

(1)关于 epoll 操作的三大系统函数: epoll_create ( … ) 、 epoll_ctl ( … ) 、 epoll_wait(…)。具体的函数原型略。这些函数完成了 epoll 对象的创建、 套接字往 epoll 红黑树中的添加、修改 与 删除 。 本文的整理…

算法随笔_30: 去除重复字母

上一篇:算法随笔_29:最大宽度坡_方法3-CSDN博客 题目描述如下: 给你一个字符串 s ,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证 返回结果的字典序最小(要求不能打乱其他字符的相对位置)。 示例 1: …

Vue 3 30天精进之旅:Day 08 - 组件通信

在Vue 3的开发过程中,组件之间的通信是一个至关重要的概念。理解如何在父子组件、兄弟组件以及通过全局事件总线进行通信,将帮助我们构建更为灵活和可维护的应用。在今天的学习中,我们将探讨以下几个方面: 父子组件之间的通信兄弟…

【Hadoop】Hadoop 概述

Hadoop 概述 Hadoop 是什么Hadoop 发展历史Hadoop 三大发行版本Hadoop 优势(4 高)Hadoop 组成(面试重点)HDFS 架构概述YARN 架构概述MapReduce 架构概述HDFS、YARN、MapReduce 三者关系 大数据技术生态体系 Hadoop 是什么 Hadoop…

网络爬虫学习:应用selenium获取Edge浏览器版本号,自动下载对应版本msedgedriver,确保Edge浏览器顺利打开。

一、前言 我从24年11月份开始学习网络爬虫应用开发,经过2个来月的努力,于1月下旬完成了开发一款网络爬虫软件的学习目标。这里对本次学习及应用开发进行一下回顾总结。 前几天我已经发了一篇日志(网络爬虫学习:应用selenium从搜…

关于使用微服务的注意要点总结

一、防止过度设计 微服务的拆分一定要结合团队人员规模来考虑,笔者就曾遇到过一个公司的项目,是从外部采购回来的,微服务划分为十几个应用,我们在此项目基础上进行自行维护和扩展。由于公司业务规模不大,而且二次开发的…

CSS Fonts(字体)

CSS Fonts(字体) 在网页设计中,字体是传达信息情感和风格的关键元素。CSS(层叠样式表)提供了丰富的字体样式和属性,使得网页设计者能够根据需求选择合适的字体,从而提升用户体验。本文将详细介绍CSS字体相关的知识,包括字体的选择、加载、样式设置等。 字体的选择 选…

week08_文本匹配任务

1、文本匹配任务概述 狭义: 给定一组文本,判断其是否语义相似 今天天气不错 match 今儿个天不错呀 √ 今天天气不错 match 你的代码有bug 以分值形式给出相似度 今天天气不错 match 今儿个天不错呀 0.9 今天天气不错 match…

Deepseek技术浅析(一)

DeepSeek 是北京深度求索人工智能基础技术研究有限公司推出的人工智能技术品牌,专注于大语言模型(LLM)的研发与应用。其技术涵盖了从模型架构、训练方法到应用部署的多个层面,展现出强大的创新能力和应用潜力。以下将详细介绍 Dee…

火出圈的DeepSeeK R1详解

各位宝子们,新年好! 模型特性 DeepSeek-R1是一款创新的AI推理模型,具有多项独特特性: 高性能推理能力 :在数学、代码和自然语言推理等任务上表现出色,性能对标OpenAI o1正式版。 强化学习驱动的训练 :采用大规模强化学习技术,仅需极少量标注数据,显著提升推理能力。…

Kafka 副本机制(包含AR、ISR、OSR、HW 和 LEO 介绍)

文章目录 Kafka 副本机制(包含AR、ISR、OSR、HW 和 LEO 介绍)1. 副本的基本概念2. 副本同步和一致性2.1 AR(Assigned Replicas)2.2 ISR(In-Sync Replicas)2.3 OSR(Out-of-Sync Replicas&#xf…

【JavaEE】_MVC架构与三层架构

目录 1. MVC架构 2. 三层架构 3. MVC架构与三层架构的对比 3.1 MVC与三层架构的对比 3.2 MVC与三层架构的共性 1. MVC架构 在前文已介绍关于SpringMAC的设计模式,详见下文: 【JavaEE】_Spring Web MVC简介-CSDN博客文章浏览阅读967次,点…

CAPL与外部接口

CAPL与外部接口 目录 CAPL与外部接口1. 引言2. CAPL与C/C++交互2.1 CAPL与C/C++交互简介2.2 CAPL与C/C++交互实现3. CAPL与Python交互3.1 CAPL与Python交互简介3.2 CAPL与Python交互实现4. CAPL与MATLAB交互4.1 CAPL与MATLAB交互简介4.2 CAPL与MATLAB交互实现5. 案例说明5.1 案…

【Matlab高端绘图SCI绘图模板】第006期 对比绘柱状图 (只需替换数据)

1. 简介 柱状图作为科研论文中常用的实验结果对比图,本文采用了3组实验对比的效果展示图,代码已调试好,只需替换数据即可生成相关柱状图,为科研加分。通过获得Nature配色的柱状图,让你的论文看起来档次更高&#xff0…

随机森林例子

完整代码: # 导入必要的库 from sklearn.datasets import load_iris from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score import numpy as np# 加载鸢尾花数…

【QT】 控件 -- 显示类

🔥 目录 [TOC]( 🔥 目录) 1. 前言 2. 显示类控件2.1 Label 1、显示不同文本2、显示图片3、文本对齐、自动换行、缩进、边距4、设置伙伴 3.2 LCD Number 3.3 ProgressBar 3.4 Calendar Widget 3. 共勉 🔥 1. 前言 之前我在上一篇文章【QT】…

SpringBoot中@Valid与@Validated使用场景详解

SpringBoot中Valid与Validated使用场景详解 在实际开发中,参数校验是保证接口安全性和数据完整性的重要手段。Spring Boot提供了Valid和Validated两个核心注解来实现参数校验,但许多开发者对它们的区别和使用场景存在疑惑。本文将深入解析二者的差异&am…

基于PyQt设计的智能停车管理系统

文章目录 一、前言1.1 项目介绍【1】项目开发背景【2】设计实现的功能【3】设计意义【4】国内外研究现状【6】摘要1.2 设计思路1.3 系统功能总结1.4 开发工具的选择【1】VSCODE【2】python【3】ptqt【4】HyperLPR31.5 参考文献二、安装Python环境1.1 环境介绍**1.2 Python版本介…

前端-Rollup

Rollup 是一个用于 JavaScript 的模块打包工具,它将小的代码片段编译成更大、更复杂的代码,例如库或应用程序。它使用 JavaScript 的 ES6 版本中包含的新标准化代码模块格式,而不是以前的 CommonJS 和 AMD 等特殊解决方案。ES 模块允许你自由…

数仓ETL测试

提取,转换和加载有助于组织使数据在不同的数据系统中可访问,有意义且可用。ETL工具是用于提取,转换和加载数据的软件。在当今数据驱动的世界中,无论大小如何,都会从各种组织,机器和小工具中生成大量数据。 …