【Java】HashMap 背诵版

HashMap 背诵版

  • 1. HashMap、Hashtable 和 ConcurrentHashMap 的区别?
    • 1.1 线程安全:
    • 1.2 继承关系:
    • 1.3 允不允许null值:
  • 2. HashMap 的数据结构
    • 2.1 什么是hash表?
    • 2.2 HashMap 的数据结构
  • 3. 什么是hash冲突,怎么解决?
    • 3.1 什么是hash冲突?
    • 3.2 为什么不能完全避免hash冲突?
    • 3.2 hash冲突怎么解决?
      • (1)开放定址法(再散列法)
      • (2)再哈希法
      • (3)建立公共溢出区
      • (4)链地址法
  • 4. 为什么在 JDK8 中 HashMap 要转成红黑树?
    • 4.1 为什么不继续使用链表?
    • 4.2 为什么是红黑树?
      • (1)二叉树
      • (2)二叉平衡树
      • (3)红黑树(自平衡二叉查找树)

1. HashMap、Hashtable 和 ConcurrentHashMap 的区别?

1.1 线程安全:

HashMap 是非线程安全的。

Hashtable 中的方法是同步的,所以它是线程安全的。

ConcurrentHashMap 在 JDK1.8 之前,使用分段锁以在保证线程安全的同时获得更大的效率。JDK1.8 开始舍弃了分段锁,使用 自旋 + CAS + synchronized 来实现同步。官方的解释中:一是节省内存空间 ,二是分段锁需要更多的内存空间,而大多数情况下,并发粒度达不到设置的粒度,竞争概率较小,反而导致更新的长时间等待(因为锁定一段后整个段就无法更新了)三是提高GC效率。

1.2 继承关系:

HashTable 是基于陈旧的 Dictionary 类继承来的。

HashMap 继承的抽象类 AbstractMap 实现了 Map 接口。

ConcurrentHashMap 同样继承了抽象类 AbstractMap,并且实现了 ConcurrentMap 接口。

1.3 允不允许null值:

HashTable 中,key 和 value 都不允许出现 null 值,否则会抛出 NullPointerException 异常。

HashMap 中,null 可以作为 key、value 都可以。

ConcurrentHashMap 中,key、value 都不允许为 null。

2. HashMap 的数据结构

2.1 什么是hash表?

哈希表(Hash Table)是一种常见的数据结构,也被称为散列表。它通过使用哈希函数将键映射到存储桶中,以实现高效的键值对存储和查找操作。

哈希表的基本原理是,通过将键(key)作为输入,经过哈希函数的计算,得到一个对应的哈希码(hash code)。这个哈希码通常是一个整数,用于确定键在哈希表中的存储位置。

哈希表内部由一个数组(数组的每个元素称为桶)和哈希函数组成。当需要存储一个键值对时,哈希函数计算出键的哈希码,并将其映射到对应的桶中。如果多个键具有相同的哈希码,即发生哈希冲突,常见的解决方法是使用链表或开放地址法来处理冲突。

在哈希表中,通过键的哈希码可以快速定位到对应的桶,从而实现快速的查找和插入操作。哈希表的平均时间复杂度为 O(1),即常数时间,但在最坏情况下,哈希冲突较多时,时间复杂度可能会退化为 O(n),其中n是存储的键值对数量。

哈希表在实际应用中被广泛使用,例如在编程语言中的字典(Dictionary)或映射(Map)数据结构中,用于高效地存储和查找键值对。

2.2 HashMap 的数据结构

在 Java 中,保存数据有两种比较简单的数据结构:数组链表

数组的特点是:寻址容易,插入和删除困难;而链表的特点是:寻址困难,插入和删除容易。

  • JDK1.8 以前 HashMap 内部数据结构使用 数组 + 链表 进行存储。(了解即可)

  • JDK1.8 以后 HashMap 内部数据结构使用 数组 + 链表 + 红黑树 进行存储。

在这里插入图片描述

3. 什么是hash冲突,怎么解决?

3.1 什么是hash冲突?

哈希表内部由一个数组(数组的每个元素称为桶)和哈希函数组成。当需要存储一个键值对时,哈希函数计算出键的哈希码,并将其映射到对应的桶中。如果多个不同键具有相同的哈希码,即发生哈希冲突

比如:对应不同的 key 可能获得相同的 hash code,即 key1 ≠ key2,但是H(key1) = H(key2)。

3.2 为什么不能完全避免hash冲突?

  1. 哈希函数是从关键字集合和地址集合的映像,通常关键字集合为无限大、长度不受限制(密码、或者文件都可以作为关键字),而地址集合却有限,无限量映射到有限量上肯定是存在重合的部分,这就是冲突。

  2. 哈希函数的复杂性:设计一个完全避免冲突的哈希函数是非常困难的。哈希函数需要具备均匀地将输入映射到输出空间的特性,但在实际情况下,很难找到一个完美的哈希函数,尤其是当输入数据的特征和分布较为复杂时。

尽管无法完全避免哈希冲突,但我们可以通过合理选择和设计哈希函数、调整哈希表的大小和负载因子等方法来降低冲突的概率。此外,使用解决冲突的方法,如链表法或开放地址法,可以处理哈希冲突并保证数据的正确性和高效性。

3.2 hash冲突怎么解决?

(1)开放定址法(再散列法)

开放定址法就是一旦发生了冲突,就去寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找到,并将记录存入。

(2)再哈希法

当哈希地址发生冲突用其他的函数计算另一个哈希函数地址,直到冲突不再产生为止。

(3)建立公共溢出区

将哈希表分为基本表和溢出表两部分,发生冲突的元素都放入溢出表中。

(4)链地址法

HashMap 把冲突的这些 key 组成一个单向链表,然后采用尾插法,把这样一个 key 保存到链表的尾部,另外为了避免链表过长影响查询效率,在链表长度大于 8,并且数组长度大于等于 64 的时候,HashMap 会把当前链表转化为红黑树,从而减少链表查询时间复杂度的问题,来提升查询效率。

4. 为什么在 JDK8 中 HashMap 要转成红黑树?

4.1 为什么不继续使用链表?

HashMap 解决hash冲突是通过链地址法完成的,在 JDK8 之前,如果产生冲突,就会把新增的元素增加到当前桶所在的链表中。

这样就会产生一个问题,当某个 bucket 冲突过多的时候,其指向的链表就会变得很长,这样如果 put 或者 get 该 bucket 上的元素时,复杂度就无限接近于O(N),这样显然是不可以接受的。

所以在 JDK1.7 的时候,在元素 put 之前做 hash 的时候,就会充分利用扰动函数,将不同 key 的 hash 尽可能的分散开。不过这样做起来效果还不是太好,所以当链表过长的时候,我们就要对其数据结构进行修改。

4.2 为什么是红黑树?

(1)二叉树

所谓的二叉查找树,一定是 left < root < right,这样我们遍历的时间复杂度就会由链表的 O(N) 变为二叉查找树的 O(logN),二叉查找树如下所示:

在这里插入图片描述

二叉搜索树通过增加了一条搜索路径,提高了查询效率,查找的效率取决于树的深度(高度)。但是,对于极端情况,当子节点都比父节点大或者小的时候,二叉查找树又会退化成链表,查询复杂度会重新变为 O(N),如下所示:

在这里插入图片描述

(2)二叉平衡树

二叉平衡树会在每次插入操作时来检查每个节点的左子树和右子树的高度差至多等于1,如果 >1,就需要进行左旋或者右旋操作,使其查询复杂度一直维持在 O(logN)。

但是这样就万无一失了吗?其实并不然,我们不仅要保证查询的时间复杂度,还需要保证插入的时间复杂度足够低,因为平衡二叉树要求高度差最多为 1,非常严格,导致每次插入都需要左旋或者右旋,极大的消耗了插入的时间。

在这里插入图片描述
对于那些插入和删除比较频繁的场景,AVL树显然是不合适的。为了保证查询和插入的时间复杂度维持在一个均衡的水平上,所以就引入了红黑树

(3)红黑树(自平衡二叉查找树)

在红黑树中,所有的叶子节点都是黑色的的空节点,也就是叶子节点不存数据;任何相邻的节点都不能同时为红色,红色节点是被黑色节点隔开的,每个节点,从该节点到达其可达的叶子节点的所有路径,都包含相同数目的黑色节点。

我们可以得到如下结论:红黑树不会像 AVL树 一样追求绝对的平衡,它的插入最多两次旋转,删除最多三次旋转,在频繁的插入和删除场景中,红黑树的时间复杂度,是优于AVL树的。

在这里插入图片描述

综上所述,这就是HashMap选择红黑树的原因。

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

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

相关文章

Go 复合数据类型之结构体与自定义类型

Go 复合数据类型之结构体与自定义类型 文章目录 Go 复合数据类型之结构体与自定义类型一、类型别名和自定义类型1.1 类型定义&#xff08;Type Definition&#xff09;简单示例 1.2 类型别名简单示例 1.3 类型定义和类型别名的区别 二、结构体2.1 结构体介绍2.2 结构体的定义2.…

day-65 代码随想录算法训练营(19)图论 part 04

463.岛屿的周长 分析&#xff1a; 1.陆地的旁边是海面&#xff0c;存在周长2.陆地在边界上&#xff0c;存在周长 思路一&#xff1a;深度优先遍历 1.通过记录访问情况来访问数据 class Solution { public:int direct[4][2]{{0,1},{0,-1},{1,0},{-1,0}};int res0;void dfs(…

集群服务器

文章目录 项目名:实现集群服务器技术栈通过这项目你学到(或者复习到)实现功能编码环境json环境muduo库boost库MySql数据库登录mysql&#xff1a;查看mysql服务开启了没有&#xff1f;mysql的服务器及开发包库chat&#xff0c;表 allgroup friend groupuser offlinemessage user…

从零开始学习线性回归:理论、实践与PyTorch实现

文章目录 &#x1f966;介绍&#x1f966;基本知识&#x1f966;代码实现&#x1f966;完整代码&#x1f966;总结 &#x1f966;介绍 线性回归是统计学和机器学习中最简单而强大的算法之一&#xff0c;用于建模和预测连续性数值输出与输入特征之间的关系。本博客将深入探讨线性…

Mac上protobuf环境构建-java

参考文献 getting-started 官网pb java介绍 maven protobuf插件 简单入门1 简单入门2 1. protoc编译器下载安装 https://github.com/protocolbuffers/protobuf/releases?page10 放入.zshrc中配置环境变量  ~/IdeaProjects/test2/ protoc --version libprotoc 3.12.1  …

Javascript文件上传

什么是文件上传 文件上传包含两部分&#xff0c; 一部分是选择文件&#xff0c;包含所有相关的界面交互。一部分是网络传输&#xff0c;通过一个网络请求&#xff0c;将文件的数据携带过去&#xff0c;传递到服务器中&#xff0c;剩下的&#xff0c;在服务器中如何存储&#xf…

基于SpringBoot的电影评论网站

目录 前言 一、技术栈 二、系统功能介绍 电影信息管理 电影评论回复 电影信息 用户注册 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了电影评…

Pyhon-每日一练(1)

&#x1f308;write in front&#x1f308; &#x1f9f8;大家好&#xff0c;我是Aileen&#x1f9f8;.希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流. &#x1f194;本文由Aileen_0v0&#x1f9f8; 原创 CSDN首发&#x1f412; 如…

Vue中如何进行分布式路由配置与管理

Vue中的分布式路由配置与管理 随着现代Web应用程序的复杂性不断增加&#xff0c;分布式路由配置和管理成为了一个重要的主题。Vue.js作为一种流行的前端框架&#xff0c;提供了多种方法来管理Vue应用程序的路由。本文将深入探讨在Vue中如何进行分布式路由配置与管理&#xff0…

Spring Boot中的@Controller使用教程

一 Controller使用方法&#xff0c;如下所示&#xff1a; Controller是SpringBoot里最基本的组件&#xff0c;他的作用是把用户提交来的请求通过对URL的匹配&#xff0c;分配个不同的接收器&#xff0c;再进行处理&#xff0c;然后向用户返回结果。下面通过本文给大家介绍Spr…

Java方法:重复使用的操作可以写成方法哦

&#x1f451;专栏内容&#xff1a;Java⛪个人主页&#xff1a;子夜的星的主页&#x1f495;座右铭&#xff1a;前路未远&#xff0c;步履不停 目录 一、方法的概念1、什么是方法&#xff1f;2、方法的定义3、方法调用的过程 二、方法重载1、重载的概念2、方法签名 在日常生活中…

计算机网络 快速了解网络层次、常用协议、常见物理设备。 掌握程序员必备网络基础知识!!!

文章目录 0 引言1 基础知识的定义1.1 计算机网络层次1.2 网络供应商 ISP1.3 猫、路由器、交换机1.4 IP协议1.5 TCP、UDP协议1.6 HTTP、HTTPS、FTP协议1.7 Web、Web浏览器、Web服务器1.8 以太网和WLAN1.9 Socket &#xff08;网络套接字&#xff09; 2 总结 0 引言 在学习的过程…

【Java-LangChain:使用 ChatGPT API 搭建系统-2】语言模型,提问范式与 Token

第二章 语言模型&#xff0c;提问范式与 Token 在本章中&#xff0c;我们将和您分享大型语言模型&#xff08;LLM&#xff09;的工作原理、训练方式以及分词器&#xff08;tokenizer&#xff09;等细节对 LLM 输出的影响。我们还将介绍 LLM 的提问范式&#xff08;chat format…

postgresql-物化视图

postgresql-物化视图 物化视图创建物化视图刷新物化视图修改物化视图删除物化视图 物化视图 创建物化视图 postgresql使用create materialized view 语句创建视图 create materialized view if not exists name as query [with [NO] data];-- 创建一个包含员工统计信息的物化…

java遇到的问题

java遇到的问题 Tomcat与JDK版本问题 当使用Tomcat10的版本用于springmvc借用浏览器调试时&#xff0c;使用JDK8浏览器会报异常。 需要JDK17&#xff08;可以配置多个JDK环境&#xff0c;切换使用&#xff09;才可以使用&#xff0c;配置为JAVA_HOME路径&#xff0c;否则&a…

【AI视野·今日Robot 机器人论文速览 第四十七期】Wed, 4 Oct 2023

AI视野今日CS.Robotics 机器人学论文速览 Wed, 4 Oct 2023 Totally 40 papers &#x1f449;上期速览✈更多精彩请移步主页 Interesting: &#x1f4da;基于神经网络的多模态触觉感知, classification, position, posture, and force of the grasped object多模态形象的解耦(f…

苹果系统_安装matplotlib__pygame,以pycharm导入模块

为了更便捷、连贯的进行python编程学习&#xff0c;尽量在开始安装python软件时&#xff0c;将编辑器、模块一并安装好&#xff0c;这样能避免以后版本冲突的问题。小白在开始安装pycharm、pip、matplotlib往往会遇到一些问题&#xff0c;文中列示其中部分bug&#xff0c;供大家…

VL53L5CX驱动开发(1)----驱动TOF进行区域检测

VL53L5CX驱动开发----1.驱动TOF进行区域检测 闪烁定义视频教学样品申请源码下载主要特点硬件准备技术规格系统框图应用示意图区域映射生成STM32CUBEMX选择MCU 串口配置IIC配置X-CUBE-TOF1串口重定向代码配置Tera Term配置演示结果 闪烁定义 VL53L5CX是一款先进的飞行感应&…

Reset信号如何同步?

首先来复习一个更加基础的概念&#xff1a;同步reset和异步reset。 同步reset&#xff08;synchronous reset&#xff09;是说&#xff0c;当reset信号为active的时候&#xff0c;寄存器在下一个时钟沿到来后被复位&#xff0c;时钟沿到来之前寄存器还是保持其之前的值。 异步…

xxl-job的原理(2)—调度中心管理注册信息

一、调度中心管理注册信息 1.JobApiController 执行器调用调度中心的url来实现注册、下线、回调等操作&#xff1b;其主要的实现类是JobApiController&#xff0c;调用/api/registry接口注册执行器信息&#xff0c;调用/api/registryRemove接口下线执行器信息&#xff0c;调用…