文章目录

  • 引入:TreeMap的局限性
  • 哈希表概念
  • 哈希冲突 以及JDK1.8的哈希冲突是如何解决的
  • 哈希函数
  • 不同数据类型对应的哈希函数
    • int 和 float
    • long 和 double
    • 字符串的哈希值计算
    • 关于自定义对象的哈希值计算方法
    • 区分Key与哈希值与索引与Value!!!

引入:TreeMap的局限性


哈希表概念

如下:说实话第一次看到这个,直接用Key值当索数组引,我寻思这不就一大型数组吗,确实是做到了添加删除搜索全部O1,但是也真是浪费了很多空间

看到后面,哦,原来上面是开玩笑的,哈希表通过引入哈希函数的概念,解决了浪费空间的问题,哈希函数就是通过Key值通过函数计算这个元素在数组中的真实索引,这样就可以做到既是数组存储,又一个Key对应一个数组元素,并不浪费空间


哈希冲突 以及JDK1.8的哈希冲突是如何解决的

如图

JDK1.8使用链地址法解决哈希冲突,在添加元素时,计算索引,若索引处已经有一个或多个元素,则比较新添加元素的Key与索引处元素链表里的Key,比较直到链表尾部,若Key不重合则直接在链表尾部添加。所以自然不用双向链表


哈希函数

就是计算哈希值的函数
哈希函数通过Key计算数组内的索引,所以要求计算出来的索引一定是要在数组的最大长度以内的,所以下面的%运算和与(&&)运算都可以做到,最后计算出来的结果在数组长度以内,但是与运算对于计算机而言效率更高


不同数据类型对应的哈希函数

int 和 float

如下图为 int 类型和 float类型的哈希函数
在选择哈希函数时,要尽量遵守两个原则:

  1. 尽量让生成的哈希值彼此唯一
  2. 尽量让Key的所有信息参与运算生成哈希值

long 和 double

long和double属于转换成二进制属于64位,而java中规定hash函数的返回值只能是一个32位的int值,所以这两位的哈希函数要通过64位的计算,生成一个32位的哈希值

小尖尖是亦或运算,二者相同则为1,二者相反则为0
就是先把long和double转换成64位二进制表达,然后取前32位和后32位进行亦或运算,生成一个32位的哈希值,这样64位就都参与生成了哈希值。

字符串的哈希值计算

字符串的哈希值就是用类似把二进制转换成十进制的过程,每个字符×31的位数减一次幂,加上后面的字符同样如此,其中字符在运算过程中被转换成为对应的ASCII码

为什么是31呢,这是一个数学问题,我们只需要知道i×31可以表达为位运算左移5位在减去i就可以了,位运算效率比较高,而java内部也确实是这么转化的,关于为什么是31可以看下面这张更具体

关于自定义对象的哈希值计算方法

默认自定义对象在的哈希函数的参数是 对象实体的地址 ,也就是说哈希值是通过地址计算出来的。
但这导致了一个问题,两个内容相同的对象因为地址不同,而在哈希表中被视为两个不同的元素,想要解决这个问题就需要自己重写一个hashcode函数,重写的函数计算方法类似字符串,是每个元素的哈希值*31的n次幂加起来的和:如下图
同时又导致了一个问题,就是如果对象插入时索引处已经有了元素,这时候就要在索引处单链表进行比较,比较已经有的元素与插入的元素Key是否相同,而官方的比较方法是比较地址,这样就会造成索引处有可能存储两个内容相同但是地址不同的自定义对象,为了解决这个问题,我们可以自己写一个对象比较equal函数
只有同时自己实现了hashCode函数与equal函数,才能保证哈希表中不会存储两个内容相同但地址不同的自定义对象Key。

只重写equal函数,会导致

区分Key与哈希值与索引与Value!!!

学着学着总把这三个搞混,Key是一个对象,对应一个value,一个Key只能对应一个哈希值和一个索引,而一个哈希值或一个索引可能对应多个key和value,哈希值是哈希函数通过Key计算出来的值,尽力做到一个Key对应一个哈希值,但依然有可能给多个Key计算出来哈希值一样,而索引=哈希值%哈希表长度,也就是数组中的真实下标。

2021-10-20 哈希表 恋上数据结构笔记相关推荐

  1. 归并排序算法 C++实现与时间复杂度(考过)恋上数据结构笔记

    复习梗概 画图,自己整个数组,看代码写步骤,这个对理解归并排序还是很有必要的 合并两个有序数组的merge函数写法 时间复杂度的分析方法!!! 其实我觉得去b站找个动态的步骤分解视频也是不错的复习方法 ...

  2. 计数排序及其改进 C++代码实现与分析 恋上数据结构笔记

    文章目录 复习梗概 算法思想 基础思想 改进空间复杂度,改进不能对负数进行排序问题 改进稳定性 计数排序时间空间复杂度 计数排序基础版 代码及输出 计数排序第一次改进版 代码及输出 计数排序终极版 代 ...

  3. 基数排序及其思想 C++代码实现及分析 恋上数据结构笔记

    文章目录 复习梗概 算法思想 时间及空间复杂度 基数排序基础版代码 及输出结果 计数排序函数 基数排序函数 可视化输出 另一种思路 完整版代码 复习梗概 思想 如何取数字各个位位数 计数排序保证稳定性 ...

  4. 快速排序 C++代码实现及其算法思想及时间复杂度分析及优化 恋上数据结构笔记

    文章目录 复习梗概 算法思想 算法复杂度分析及稳定性 如何优化? 快速排序改进版代码C++ 快速排序个人青春版代码 完整代码 复习梗概 算法思想,别的排序名字直接就能让人联想到它的算法思想,唯独快速排 ...

  5. 插入排序算法 及其二分搜索优化版 C++代码实现 恋上数据结构笔记

    复习梗概 文章目录 复习梗概 插入排序算法思想 插入排序时间复杂度与特性(多少,与什么有关?) 插入排序基础版 插入排序2nd优化版(优化了哪里?) !!!插入排序二分搜索优化版(优化了哪里?如何优化 ...

  6. 堆排序 C++代码实现及思想 排序过程输出 恋上数据结构笔记

    复习梗概 文章目录 复习梗概 什么是堆思想? 堆排序算法怎么来的? 什么是下滤?代码 什么是建堆?代码 堆排序本体 代码及排序过程输出 和时间复杂度 完整代码 什么是堆思想? 最大堆:树形结构,每一个 ...

  7. 2021-10-15 红黑树 概念和平衡操作理解以及与AVL对比分析 恋上数据结构笔记

    文章目录 红黑树的由来 红黑树需要遵守的五大规则 红黑树与4阶B树的相互转换!! 红黑树的插入(12种情况) 红黑树的删除(3大类情况) 红黑树的平衡 以及与AVL树的性能比较 红黑树的由来 红黑树: ...

  8. 2021-10-11 ! AVL树 及其平衡调整 四种情况 恋上数据结构笔记 (考过)

    b站有个up讲的很详细 https://www.bilibili.com/video/BV1xE411h7dd?from=search&seid=11383601726930144190&am ...

  9. 希尔排序(缩小增量排序)(插入排序的优化版) C++代码实现及算法分析 恋上数据结构笔记

    文章目录 复习概要 算法思想 算法流程 算法复杂度分析及稳定性 希尔排序代码正常版 希尔排序与插入排序代码对比 希尔排序个人青春版(别看以免走上歧途) 复习概要 算法思想与流程 分这么多组分别插入排序 ...

最新文章

  1. VI连接esx主机时报错“client.xml”错误
  2. 【Python学习系列三】Windows下Python第三方常用库安装
  3. 【IT笔试面试题整理】反转链表
  4. js slice 参数为负值
  5. LeetCode 1005. K 次取反后最大化的数组和
  6. SecureCRT防止自动断开
  7. binlog关闭事务记录_【MySQL】binlog_format以及binlog事务记录分析
  8. Eureka缓存机制
  9. 从单体架构迁移到微服务,8个关键的思考、实践和经验
  10. 淘宝flexible.js的使用
  11. 8.Linux 高性能服务器编程 --- 高性能服务器程序框架
  12. Lisp-Stat翻译 —— 第十章 一些动态绘图实例
  13. 一些dalao的模板
  14. Node.js 单元测试:我要写测试 - Mocha - Nodejs开源项目里怎么样写测试、CI和代码测试覆盖率
  15. android自动照相机2.0,Camera2.0下载
  16. GitHub 上排名前 100 的 Android 开源库介绍
  17. USB串口导致鼠标乱跳
  18. PHP中的addslashes双胞胎兄弟函数
  19. 从内存播放Flash。
  20. 自动化之RPA工具之UiBot

热门文章

  1. 802.11 帧格式及类型
  2. 关于STM32串口空闲中断的问题
  3. AB1601继电器干扰问题
  4. 用Go语言建立一个简单的区块链part7:网络
  5. 不同语言编译的程序入口总结
  6. agilebpm脑图_干货基于SpringBoot2开发的Activiti引擎流程管理项目脚手架
  7. (39)通过 PID 获取 EPROCESS
  8. angr学习笔记(9)(添加约束)
  9. Request模块基本常识
  10. PC微信逆向:分析通用设置数组