面试篇-深入理解 Java 中的 HashMap 实现原理

news2025/1/18 16:59:52

一、HashMap实现原理

HashMap 的实现主要包括两个部分:哈希函数和解决哈希冲突的方法。

1.哈希函数

当使用 put() 方法将键值对存储在 HashMap 中时,首先需要计算键的哈希值。HashMap 使用 hashCode() 方法获取键的哈希值,并将其转换为桶(bucket)的索引位置。具体的哈希函数实现可能会因 JVM 和 Java 版本而异。

2.解决哈希冲突的方法

由于不同的键可能具有相同的哈希值,因此 HashMap 需要一种方法来处理这种情况。HashMap 使用链表或红黑树等数据结构来存储具有相同哈希值的键值对。如果桶中已经存在一个键,则新的键值对将添加到该键所在的链表或红黑树中。如果没有任何键与当前键具有相同的哈希值,则新的键值对将直接添加到桶中。

3.扩容机制

当存储在 HashMap 中的键值对的数量超过负载因子乘以散列表容量时,HashMap 将自动扩容。在扩容时,HashMap 会创建一个新的桶数组,并通过重新哈希化将所有键值对复制到新的桶中。这可以确保哈希函数仍然能够正常工作,并且具有足够的空间来存储新的键值对。

以下是jdk1.7与jdk1.8中hashmap的区别:

JDK1.7

JDK1.8

存储

数组+链表

数组+链表+红黑树

位置算法

h & (length-1)

h & (length-1)

链表超过8

链表

红黑对(链表超过8且数组长度超64)

节点结构

Entry<K,V> implements Map.Entry<K,V>

Node<K,V> implements Map.Entry<K,V>

插法

头插法(扩容环化造成死循环)

尾插法

1、JDK1.7

使用一个Entry数组来存储数据,用key的hashcode取模来决定key会被放到数组里的位置,如果hashcode取模后的结果相同,那么这些key会被定位到Entry数组的同一个格子里,这些key会形成一个链表;这样数据遍历时间就过长。1.7中hashmap链表插入的方式是使用头插法。

2、JDK1.8

使用一个Node数组来存储数据,但是这个Node可能是链表结构,也可能是红黑树结构;如果插入的元素key的hashcode值相同,那么这些key也会被定位到Node数组的同一个格子里,如果不超过8个使用链表存储,超过8个且Node数组长度超过64,会将链表转换为红黑树。1.8中hashmap链表插入的方式是使用尾插法。

二、相关问题

【问题一】为什么jdk1.8后改为尾插法?

主要是因为头插法在多线程扩容情况下会引起链表环。那什么是链表环呢?

线程1,第一节点为A,第二节点为B后面就没有了,遍历过程为A->B然后B没有后面节点即遍历结束。

这时线程1挂起。线程2引发扩容,扩容后为B->A。这时线程1遍历就会发现A的下一节点是B,会发现遍历B时B还有后续的节点为A,这样就出样链表环了。

【问题二】什么是HashMap,它的工作原理是什么?

HashMap是Java集合框架中的一种实现,可以用来存储键值对。HashMap使用哈希表来实现,它通过将键映射到哈希表中的一个位置来存储和访问值。

【问题三】HashMap如何处理哈希冲突?

当两个键映射到哈希表中的同一个位置时,称为哈希冲突。HashMap使用链地址法来处理哈希冲突,即在哈希表中每个桶都维护一个链表,所有哈希值相同的键值对都被放置在这个链表中。

【问题四】HashMap的初始容量和负载因子是什么意思?它们对HashMap的性能有什么影响?

初始容量表示哈希表在创建时包含的桶数。负载因子是哈希表在自动扩容之前可以达到的平均填充因子的阈值。默认情况下,初始容量为16,负载因子为0.75。如果元素数量超过了容量*负载因子,哈希表将自动扩容,这可能会导致性能下降。

【问题五】如何实现一个线程安全的HashMap?

可以使用ConcurrentHashMap类来实现线程安全的HashMap。ConcurrentHashMap使用锁分段技术来实现线程安全,即将哈希表分成多个段,每个段上都有一个锁,不同的线程可以同时访问不同的段。

【问题六】HashMap与Hashtable有什么区别?

HashMap和Hashtable都是用来存储键值对的集合类,它们的主要区别在于:

  • 线程安全性:Hashtable是线程安全的,而HashMap不是。因此,在多线程环境下,如果需要使用Map来存储数据,应该使用ConcurrentHashMap而不是HashMap。

  • null值:Hashtable不允许键或值为null,而HashMap允许。

  • 性能:Hashtable比HashMap慢,这是因为Hashtable的方法是同步的,而HashMap的方法不是。

本文正在参加「金石计划」

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

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

相关文章

Docker的常见命令

前言:使用Docker得学会的几个常见命令 常见命令前置学习: docker --help这个命令必须得会因为,很多命令是记不住的,得使用他们的官方help下面是一些实例 docker load --help常见命令集合: 一: docker images #查看全部镜像 docker rmi #删除某个镜像(例如:docker rmi redis…

Vue3——组件间通信的五种常用方式

Vue3组件间通信的五种常用方式 写在前面 本文采用<script setup>语法糖的编写方式&#xff0c;比options API更自由。 <script setup>语法糖详细内容看查看文档&#xff1a;setup语法糖官方文档 然后我们会讲以下五种常用的组件通信方式 propsemitv-modelrefs…

高速数字信号VS射频信号,到底哪个更难设计?

一博高速先生成员&#xff1a;黄刚熟悉高速先生的小伙伴们会知道&#xff0c;我们是以研究高速数字信号为主的团队&#xff0c;从不到1G到目前在研究的112G&#xff0c;高速先生就这样一直研究过来的&#xff0c;分享的案例也大多是以高速数字信号为主的案例。最近受到我们粉丝…

golang for range 令人抓狂的面试题

1.下面这段代码能否正常结束&#xff1f; func main() {v : []int{1, 2, 3}for i : range v {v append(v, i)} } 答案&#xff1a;正常结束。 可能我们会以为程序会陷入死循环。 但是我们要明白 for range 中的v其实就是复制了一份前面定义的v切片&#xff0c;不论前面定…

Python从入门到精通第3天(循环结构的使用)

循环结构for-in循环while循环break和continue关键字练习在写程序的时候&#xff0c;一定会遇到需要重复执行某条或某些指令的场景&#xff0c;例如用程序控制机器人踢足球&#xff0c;如果机器人持球而且还没有进射门范围&#xff0c;那么我们就要一直发出让机器人向球门方向移…

免费ChatGPT接入-国内怎么玩chatGPT

免费ChatGPT中文版 OpenAI 的 GPT 模型目前并不提供中文版的免费使用&#xff0c;但是有许多机器学习平台和第三方服务提供商也提供了基于 GPT 技术的中文版模型和 API。下面是一些常见的免费中文版 ChatGPT&#xff1a; Hugging Face&#xff1a;Hugging Face 是一个开源社区…

JAVAWeb03-JavaScript

1. JavaScript 1.1 概述 1.1.1 官方文档 地址: https://www.w3school.com.cn/js/index.asp 1.1.2 基本说明 JavaScript 能改变 HTML 内容&#xff0c;能改变 HTML 属性&#xff0c;能改变 HTML 样式 (CSS)&#xff0c;能完成页面的数据验证。 js演示1.html 需要把图片拷贝…

一个注解实现WebSocket集群方案,别提有多优雅了

WebSocket大家应该是再熟悉不过了&#xff0c;如果是单体应用确实不会有什么问题&#xff0c;但是当我们的项目使用微服务架构时&#xff0c;就可能会存在问题 比如服务A有两个实例A1和A2&#xff0c;前端的WebSocket客户端C通过网关的负载均衡连到了A1&#xff0c;这个时候当…

【Java数据结构】线性表-队列

线性表-队列概念队列的使用队列模拟实现循环队列如何区分空与满双端队列 (Deque)概念 队列&#xff1a;只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性表&#xff0c;队列具有先进先出FIFO(FirstIn First Out) 入队列&#xff1a;进行插入操作的…

文章生成器写出来的原创文章

文章生成机器人 文章生成机器人是一种基于人工智能技术和自然语言处理算法的程序&#xff0c;可以自动地生成高质量、原创的文章。 文章生成机器人的优点如下&#xff1a; 提高工作效率&#xff1a;文章生成机器人能够在较短的时间内自动帮助用户生成大量的文章&#xff0c;提…

GaussDB工作级开发者认证—第三章开发设计建议

一. 数据库对象命名和设计建议 二. 表设计最佳实践 三. SQL查询最佳实践 SQL 最佳实践 - SELECT 避免对大字段执行order by&#xff0c;group by等引起排序的操作避免频繁使用count()获取大表行数慎用通配符字段 “*”避免在select目标列中使用子查询统计表中所有记录数时&…

设计模式之策略模式(C++)

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 一、策略模式是什么&#xff1f; 策略模式是一种行为型的软件设计模式&#xff0c;针对某个行为&#xff0c;在不同的应用场景下&…

win下配置pytorch3d

一、配置好的环境&#xff1a;py 3.9 pytorch 1.8.0 cuda 11.1_cudnn 8_0 pytorch3d 0.6.0 CUB 1.11.0 你可能觉得pytorch3d 0.6.0版本有点低&#xff0c;但是折腾不如先配上用了&#xff0c;以后有需要再说。 &#xff08;后话&#xff1a;py 3.9 pytorch 1.12.1 cuda …

Log4j日志

log4j日志简介组成Logger 日志记录器Appender 日志目的地&#xff08;Windows下的路径分隔符&#xff09;※Layout 日志信息布局layout 指定输出的样式模板&#xff1f;layout.ConversionPattern 指定输出的每项内容及其格式顺序日志信息等级/优先级使用的Log4j的jar包代码示例…

BGP路由控制

实验要求 IP地址分配 给所有路由器按要求配置IP地址&#xff0c;AS之间使用AR编号连接作为IP&#xff0c;例如34.0.0.0/30。 在AS123中启动OSPF 启动BGP&#xff0c;并将24网段的路由宣告 R4 [r4]bgp 400 [r4-bgp]peer 24.0.0.2 as-number 123 [r4-bgp]peer 34.0.0.2 as-num…

Qt关于第三方库介绍

文章目录前言一、获取第三方库二、Makefile是什么&#xff1f;三、将第三方库添加到 Qt 项目中四、mingw和msvc的区别五、安装msvc六、安装mingw七、如何使用不同的编译器前言 本专栏的系统为&#xff1a;windows11 qt版本为&#xff1a;qt6.4.2 提示&#xff1a;以下是本篇文…

【从零开始学Skynet】实战篇《球球大作战》(五):gateway代码设计(上)

1、协议格式 在写代码之前&#xff0c;我们要先了解什么是协议&#xff0c;协议就是 “客户端向服务端发起的登录请求”&#xff0c;那么登录请求是什么样子的呢&#xff1f;这得先从TCP数据流说起&#xff0c;客户端发起的请求&#xff0c;就是一些二进制数据。 &#xff08;…

OpenCV实例(六)行人检测

OpenCV实例&#xff08;六&#xff09;行人检测1.行人检测概述2.行人检测基础实现2.1基本流程2.2实现程序2.3参数优化3.完整行人检测程序作者&#xff1a;Xiou 1.行人检测概述 行人检测是目标检测的一个分支。目标检测的任务是从图像中识别出预定义类型目标&#xff0c;并确定…

【Python】json数据解析

目录 json文件数据解析 爬虫获取王者荣耀英雄信息json数据包并解析 爬虫获取抖音视频json数据包并解析 json文件数据解析 json字符串&#xff1a;通常类似python数据类型中的列表和字典的结合&#xff0c;也可能是单独的列表或者字典格式&#xff0c;通常可以通过json模块的…

亚马逊影响搜索排名的主要因素有哪些,使用测评做排名有哪些要求?

亚马逊产品的排名越高就意味着分配的流量越多而且带来更高的销量。那主要有哪些因素影响产品的排名呢&#xff1f; 1、产品销量 产品销量反映了该产品在同类产品中的销售情况&#xff0c;该数值会在产品Listing中展示&#xff0c;平台会每小时更新一次该排行榜。在平台算法看…