【Java集合类】HashMap(一)- 散列表基础知识

news/2024/4/26 10:30:00/文章来源:https://blog.csdn.net/a34434180/article/details/129148274

什么是散列表

散列表Hash table,也叫哈希表),是根据键(Key)直接访问内存储存位置的数据结构。

一般而言,散列表通过一个散列函数将待查找的元素映射为数组下标(散列值,hash值),将元素存储在下标位置,查询时同样用这个散列函数得到下标,这样理论上定位元素的时间复杂度可以到O(1)

散列函数的设计要求

由于散列函数hash()的作用是将查找元素value映射为下标key(散列值),因此有以下基本要求

  1. 散列值为非负整数
  2. 如果value1 = value2,则hash(value1) = hash(value2),这一点是必须实现的,否则散列表就失去了基础的查找作用,你先在表中插入了一个value,当你再去寻找时却再也找不到了
  3. 如果value1 ≠ value2,则hash(value1) ≠ hash(value2),这一点也好理解,不同的value应该存到不同的位置。现实情况是这一点不能完美实现,于是出现散列(哈希)冲突

散列冲突的原因

影响散列冲突的因素一般有三点:

  1. 散列函数的设计

考虑一个极端情况,假如散列函数是个常数函数:hash() = 0,所有元素都会被映射到下标为0的位置,这种情况下散列冲突就非常严重了

当然谁也不会选这样的散列函数,但是要确保散列函数的结果足够随机,最好接近另一个极端:所有元素都被映射到不同位置

  1. 数据本身

我可能设计了一个输出结果很随机的散列函数,可如果输入数据本身被设计过也会造成散列冲突。这就不得不提到一种DoS攻击:哈希洪水攻击。如果有恶意攻击者,掌握了算法细节,专门设计了一批结果冲突的输入数据,使得所有的数据经过散列函数之后到一个槽里,散列表查询时间从o(1)退化成o(n),就能用很低的成本让服务器宕机

这时只能避免攻击者掌握算法细节,比如研究带密钥的散列函数(Keyed Hash Function

  1. 装载因子

另外,数据量和散列表容量的比重也会对散列冲突有影响,把10条数据分别插入容量为1,100、10w的散列表,第一种情况肯定会有散列冲突,而表的容量越大,冲突的概率也越小。这里数据量和散列表容量的比重也称为装载因子

之后HashMap的讲解中,我们将看看它是如何设计,从而尽量避免散列冲突,以及解决已存在的散列冲突的

解决已经发生的散列冲突

开放寻址法

  • 线性探测法:核心思想就是查找散列表中离冲突单元最近的空闲单元(hash(x)冲突,就注意探测hash(x)+1, hash(x)+2),并且把新的键插入这个空闲单元。同样的,查找也同插入如出一辙:从散列函数给出的散列值对应的单元开始查找,直到找到与键对应的值或者是找到空单元。需要注意的问题是:

    • 查找元素时,遇到散列冲突,会逐个探测邻近单元,直到查到null就认为元素不存在
    • 由上一点可知,删除元素时,不能直接置为null,而是要标记为deleted。因为置为null会导致之后查找探测到该位置时,会判断元素不存在,而实际上元素可能就在后面的单元中。
    • 插入元素时,遇到deleted的元素可以覆盖

    结合这三点可以看出,线性探测法中,所有发生散列冲突的元素(包括已删除的元素)一定是连续保存在散列表中,中间不会有null值打断。

    也因此,线探探测法有以下的问题:

    • 数据聚集:散列值本来就不会均匀分布在下标中,线性探测法会加剧聚集的现象,让某个区域冲突概率特别大,查询的时间会更长,极端情况下插入和查询都会到O(n)

    为了改进数据聚集,其他开放寻址法还有:

  • 二次探测法:和线性探测相比步长变了,hash(key)+0,hash(key)+1^2, hash(key)+2^2……

  • 双重探测法:使用一组散列函数 hash1(key), hash2(key),hash3(key)…我们先用第一个散列函数,如果计算得到的存储位置已经被占用,再用第二个散列函数

拉链法(链表法)

将散列到同一个存储位置的所有元素保存在一个链表中,是HashMap使用的思想

两种方法的比较

  1. 开放寻址法

    • 优点:
      • 数据都存储在数组中,可以有效地利用 CPU 缓存加快查询速度(连续空间)
      • 序列化更简单,链表法包含指针,序列化没那么容易
    • 缺点
      • 删除数据的时候比较麻烦
      • 所有数据都存在一个数组里,尤其装载因子大的时候,探测时间会很长(因为这条探测的路径上除了散列值相同的元素,还可能会遇到其他不同的元素)

    总结:数据量不大,用开放寻址法。这也是 Java 中的ThreadLocalMap使用开放寻址法解决散列冲突的原因。

  2. 链表法

    • 优点:
      • 对大装载因子的容忍度更高,探测的路径上只会有散列值相同的元素。极端的例子:第一次插入散列值为a的元素,后面n-2次都没冲突,第n次的元素散列值也是a但是和第一个元素key不同。这样在查找第n个元素时,线性探测法就是n,但链表法就是1
      • 链表本身要存指针,消耗更多内存,但是如果本来就要存大对象,指针大小也就可以忽略不计了

    总结:适合大数据量、大对象,并且更灵活,可以用红黑树代替链表进行查询优化

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

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

相关文章

OpenGL 渲染管线与显卡可执行程序

渲染管线的六个步骤 OpenGL 渲染管线的六个步骤,从指定几何图元到帧缓冲区写入像素,图像就被 OpenGL 引擎一步步地渲染到屏幕(FBO)上去了。 指定几何对象 OpenGL 引擎会根据开发者的指令去绘制几何图元。OpenGL(ES&…

IMX6ULL学习笔记(17)——工程管理

一、简介 之前我们把所有源码文件放在一个文件夹下。 这样做存在两个主要问题,第一,代码存放混乱不易阅读。第二,程序可移植性差。如果工程源文件达到几十、甚至数百个的时候,这样一股脑全部放到根目录下就会使工程显得混乱不堪。…

[JavaEE系列] 详解面试中HTTP协议HTTPS协议

文章目录HTTP不安全HTTPS中的加密算法对称加密非对称加密混合加密HTTPS中的摘要算法HTTPS中的数字证书SSL /TLS握手TCP建立连接(三次握手)三次握手中常见的面试题:TCP断开连接(四次挥手)四次挥手中常见的面试题&#x…

前端页面开发模块组织结构

模块组织 任何超过 1000 行的 CSS 代码,你都曾经历过这样的体验: 这个 class 到底是什么意思呢?这个 class 在哪里被使用呢?如果我创建一个 xxoo class,会造成冲突吗?Reasonable System for CSS Stylesheet Structure 的目标就是解决以上问题,它不是一个框架,而是通过…

2.5|1.3 操作系统与嵌入式操作系统概述

CPU是计算机系统的心脏,操作系统是计算机系统的大脑。半个世纪以来操作系统这门软件科学吸引了世界上一大群最热情、最有智慧的杰出人材,集中了人类现代创造性思维活动的精髓。操作系统是软件世界的万花筒、世博会,是软件王国中的一顶璀璨的皇…

十二、Django表单

表单 在之前的案例中,每次我们需要提交表单数据的时候。我们都需要去手动编辑html表单,根据不同的字段,字段名,进行编码。做了很多重复的部分,所以django提供了一个专门用来处理表单的类,django.forms.For…

代码随想录算法训练营第六天 |哈希表理论基础、242.有效的字母异位词、349. 两个数组的交集 、202. 快乐数、 1. 两数之和

打卡第六天,补昨天的卡 今日任务 哈希表理论基础242.有效的字母异位词349.两个数组的交集202.快乐数1.两数之和 哈希表理论基础 哈希表是根据关键码的值而直接进行访问的数据结构。 哈希表能解决什么问题呢? 一般哈希表都是用来快速判断一个元素是否出现集合里。 …

Tr0ll1靶机训练

信息收集 主机探测 端口扫描 21,22,80端口开放通过浏览器访问并进行指纹识别,并没没有发现什么有用信息 测试 观察发现21端口开放(ftp)尝试进行匿名登录发现其中存在一个流量文件将其下载 并将文件用wirwshark打开,追踪其TCP流(…

BEV感知:DETR3D

3D检测:DETR3D前言MethodImage Feature Extracting2D-to-3D Feature TransformationLoss实验结果前言 在这篇paper,作者提出了一个更优雅的2D与3D之间转换的算法在自动驾驶领域,它不依赖于深度信息的预测,这个框架被称之为DETR3D…

【C进阶】数据的存储

文章目录:star:1. 数据类型:star:2. 整形在内存中的存储2.1 存储规则2.2 存储模式2.3 验证大小端模式:star:3. 数据范围3.1 整形溢出3.2 数据范围的求解3.3 练习:star:4. 浮点型在内存中的存储4.1 浮点数的存储规则4.2 练习5. :star::star:总结(思维导图)⭐️1. 数据类型 在了…

Android - 代码生成远程依赖库(阿里云)

一、注册 没有注册过阿里云且没有实名认证的点这里:阿里云官网 二、查看库 阿里云制品仓库Packages (注:如果没有创建企业或个人使用,按照提示,选个人使用) 三、选择类型 选择其中一个(两…

传统巨头生“变”,中国毫米波雷达市场战火再升级

进入2023年,中国车载毫米波雷达市场战火明显升级。 一方面,愈演愈烈的份额抢夺战不仅仅存在于几大传统巨头之间,也快速转移到与国产供应商之间;随着部分外资巨头的本土化战略深入落地,同时对国产供应商造成了压力。 …

ur3+robotiq ft sensor+robotiq 2f 140配置gazebo仿真环境

ur3robotiq ft sensorrobotiq 2f 140配置gazebo仿真环境 搭建环境: ubuntu: 20.04 ros: Nonetic sensor: robotiq_ft300 gripper: robotiq_2f_140_gripper UR: UR3 通过上一篇博客配置好ur3、力传感器和robotiq夹爪的rviz仿真环境后,现在来配置一下对…

MySQL数据库————MVCC

MySQL的脏读、幻读、不可重复读 脏读 现在有两个事务在操作table表,事务B修改了id2的name字段为李老四,但是没有提交,事务A查询id2的数据,得到name为李老四;事务B发生回滚,id2的数据的name又变回李四&…

性能测试知多少?怎样开展性能测试

看到好多新手,在性能需求模糊的情况下,随便找一个性能测试工具,然后就开始进行性能测试了,在这种情况下得到的性能测试结果很难体现系统真实的能力,或者可能与系统真实的性能相距甚远。 与功能测试相比,性能…

【Spring Boot 原理分析】- 自动配置

【Spring Boot 原理分析】- 自动配置 Condition 注解 Condition 是 Spring 4.0 增加的条件判断功能,通过这个功能可以实现选择的创建 Bean 操作 👑 我们在使用 Spring 的时候,只需导入某个依赖的坐标,就可以直接通过 Autwired 注…

堆,堆构建,堆排序,PriorityQueue和TopN问题

零. 前言 堆作为一种重要的数据结构,在面笔试中经常出现,排序问题中,堆排序作为一种重要的排序算法经常被问道,大顶堆小顶堆的应用经常出现,经典的问题TopN问题也是堆的重要应用,因此,了解并掌握…

Mac - Spotlight(聚焦)

文章目录一、Mac 中 Spotlight 的使用1、调用/打开 Spotlight2、执行搜索3、Spotlight 设置二、Mac 上的 Spotlight 开发1、关于 Spotlight2、使用 NSMetadataQuery 搜索示例三、mds 和 fsevents四、命令行访问 Spotlight五、Core Spotlight Framework六、Spotlight 插件相关资…

CSS预处理器sass和less

文章目录CSS预处理器什么是CSS预处理器Sass和LESS背景介绍Sass背景介绍LESS的背景介绍Sass安装Sass下载Ruby安装文件安装Ruby安装Sass编译Sass命令行编译命令行编译配置选项四种编译排版演示nested 编译排版格式expanded 编译排版格式compact 编译排版格式compressed 编译排版格…

登录逻辑漏洞整理集合

目录一、任意用户注册1.未验证邮箱/手机号2、不安全验证邮箱/手机号3.批量注册4.个人信息伪造5.前端验证审核绕过6.用户名覆盖二、任意用户登录1、万能密码2、验证码、密码回显3、登录检测不安全三、任意账号重置1、重置账号名2、验证码3、MVC数据对象自动绑定4、Unicode字符处…