hashmap专题

news2024/9/25 15:26:22

hashmap专题

  • 常见map
  • hashMap
    • jdk1.8HashMap新变化
    • hashmap源码中重要的常量
    • 存储结构
      • put 存入数据过程
      • 取数据过程get()
      • 扩容
      • hashmap 树化/链化
      • hashmap的容量 桶的数量为什么要是2的n次方?
      • hashmap为什么线程不安全

常见map

  • hashtable线程安全,但效率太低。
  • hashmap 线程不安全。
  • LinkedHashMap线程也不安全
  • ConcurrentHashMap线程安全

hashMap

hashmap的数据结构有数组和链表来实现对数据的存储,但这2个基本上是两个极端。

  • 数组:数组的存储区是连续的,占用内存比较严重,故空间复杂度很大,但因其地址连续,查找很快。数组的特点就是,寻址容易,插入和删除困难。
  • 链表 链表的存储区离散,占用内存比较宽容,故空间复杂度小,但时间复杂度大(因其内存地址不连续,查找会慢),链表的特点:寻址慢,插入和删除容易

JDK7及以前版本,hashmap是数组+链表结构,
JDK8以后,Hashmap是数组+链表+红黑树

jdk1.8HashMap新变化

  • HashMap map = new HashMap();//默认情况下,先不创建长度为16的数组。
  • 当首次调用map.put()时,在创建长度为16的数组 。
  • 数组为Node类型,在jdk17中称为Entry数组。
  • 当数组指定索引位置的链表长度>8时,且map中的数组长度>64时,此索引位置上的所有key-value对使用红黑树进行存储。

hashmap源码中重要的常量

  • DEFAULT_INITIAL_CAPACITY : 默认16,HashMap的默认容量
  • MAXIMUM_CAPACITY :默认2^30, HashMap的最大支持容量
  • DEFAULT_LOAD_FACTOR:默认0.75, HashMap的默认加载因子
  • TREEIFY_THRESHOLD:默认8 Bucket中链表长度大于该默认值,转化为红黑树
  • UNTREEIFY_THRESHOLD: 默认6,Bucket中红黑树存储的Node小于该默认值,转化为链表
  • MIN_TREEIFY_CAPACITY: 默认64,桶中的Node被树化时最小的hash表容量。(当桶中Node的数量大到需要变红黑树时,若hash表容量小于MIN_TREEIFY_CAPACITY时,此时应执行resize扩容操作这个MIN_TREEIFY_CAPACITY的值至少是TREEIFY_THRESHOLD的4倍。)
  • table: 存储元素的数组,总是2的n次幂

存储结构

jdk1.8 put方法

在这里插入图片描述

在jdk1.8后,内部数据结构使用数组+链表+红黑树进行存储。

  • 数组类型为Node[],每个Node都保存了某个KV键值对元素的key、value、hash、next等值。
  • 链表 他由一系列节点组成,每个节点包含两部分:数据和指向下一个节点的指针。
  • 当链表的长度超过8并且数组长度大于64,为了避免查找搜索性能下降,该链表会转换成一个红黑树。

put 存入数据过程

  1. hashmap在存储数据时,会将key和value封装在一个Node[]
  2. 调用key的hashcode()方法获取key的哈希码。
  3. 通过转换算法将其转换为数组的下标。
  4. 当数组下标没有值,就直接将此Node[]放在这个下标
  5. 当数组下标下有值,就会将key和链表上的每一个值进行比较
  6. 如果equal()都返回false则将其加入链表最后
  7. 如果equal()和链表某个节点返回true则将其节点进行覆盖

取数据过程get()

  1. 根据key的值算出hashcode
  2. 通过转换算法将其转换为数组的下标
  3. 如果当前下标为null则直接返回空
  4. 如果当前下标是链表,会使用equal()方法和链表上的节点进行比较
  5. 如果都返回false则返回空
  6. 如果有一个节点为true则返回当前节点的值

扩容

  • loadFactor 负载因子,默认值0.75

当Hashmap中的元素个数超过数组大小(数组总大小length,不是数组中个数size)loadFactor 时,就 会 进 行 数 组 扩 容 , loadFactor 的 默 认 值(DEFAULT_LOAD_FACTOR)为0.75, 这是一个折中的取值。 也就是说, 默认情况下, 数组大小(DEFAULT_INITIAL_CAPACITY)为16, 那么当HashMap中元素个数超过160.75=12(这个值就是代码中的threshold值, 也叫做临界值)的时候, 就把数组的大小扩展为 2*16=32, 即扩大一倍, 然后重新计算每个元素在数组中的位置, 而这是一个非常消耗性能的操作, 所以如果我们已经预知HashMap中元素的个数, 那么预设元素的个数能够有效的提高HashMap的性能。

hashmap 树化/链化

当hashmap中的其中一个链表的对象个数达到了8个,此时如果capacity没有达到64个,那么hashmap会先扩容解决,如果已经达到了64,那么这个链会变成树,节点类型由Node变成treeNode类型。当然,如果当映射关系被移除后,下次resize方法时判断树的节点小于6个,也会把树在转换为链表。

hashmap的容量 桶的数量为什么要是2的n次方?

HashMap为了存取高效,要尽量较少碰撞,就是要尽量把数据分配均匀,每个链表长度大致相同。
关键就在于把当前数据存放到哪一个桶中,这个算法就是取模运算。

假设: length:HashMap的容量 hash:当前key的哈希值 取模运算为 hash % length
但是,在计算机中,直接取模运算的效率不如位运算(&),什么是位运算?就是对于二进制数据的按位运算,1和1才得1,其他都得0,比如:1011
& 1100 = 1000

sun公司的大牛们发现,当容量为2的n次方时,hash & (length - 1) == hash % length
,于是就在源码中做了优化,通过 hash & (length - 1) 来替代取模运算,而前提就是容量必须为2的n次方。这样做的好处在于:

提高操作运算效率(位运算效率 > 取模运算效率) 减少碰撞,数据均匀分布,提高HashMap查询效率

为什么可以减少碰撞?
举个例子,现在两个hash分别是2和3:
比如 length 为 9 的情况:3&(9-1)=0 2&(9-1)=0 ,都在0上,碰撞了;
比如 length 为 8 的情况:3&(8-1)=3 2&(8-1)=2 ,不同位置上,不碰撞;

hashmap为什么线程不安全

  1. 并发修改导致数据不一致(hash碰撞)。
  2. 并发扩容导致死循环或者数据丢失。

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

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

相关文章

《深入Linux内核架构》第2章 进程管理和调度 (6)

目录 2.8 调度器增强 2.8.1 SMP调度 2.8.2 调度域和控制组 2.8.3 内核抢占和低延迟相关工作 2.9 小结 2.8 调度器增强 2.8.1 SMP调度 进程迁移: 含义:把进程从一个CPU就绪队列迁移至另一个CPU就绪队列。 作用:CPU负荷均衡。 缺点&…

【评分标准】【网络系统管理】2019年全国职业技能大赛高职组计算机网络应用赛项H卷 无线网络勘测设计

第一部分:无线网络勘测设计评分标准 序号评分项评分细项评分点说明评分方式分值1点位设计图AP编号AP编号符合“AP型号位置编号”完全匹配5AP型号独立办公室、小型会议室选用WALL AP110完全匹配5员工寝室选用智分,其他用放装完全匹配5其它区域选用放装AP…

【原创】JDK17获取CPU占用率、内存占用率以及堆内存使用情况

前言 我之前一篇文章: 【原创】Java获取CPU占用率、内存占用率最简单的方式_java获取cpu使用率-CSDN博客 这篇文章虽然简单,但是只能针对JDK8,换成现在模块化的JDK后,OperatingSystemMXBean类就无法反射获取其中的信息了&#…

代码随想录 动态规划-股票问题

目录 121.买卖股票的最佳时机 122买卖股票的最佳时机II 123. 买卖股票的最佳时机III 188.买卖股票的最佳时机IV 309.买卖股票的最佳时机含冷冻期 714.买卖股票的最佳时机含手续费 121.买卖股票的最佳时机 121. 买卖股票的最佳时机 简单 给定一个数组 prices &…

【FLOOD FILL专题】【蓝桥杯备考训练】:扫雷、动态网格、走迷宫、画图、山峰和山谷【已更新完成】

目录 1、扫雷(Google Kickstart2014 Round C Problem A) 2、动态网格(Google Kickstart2015 Round D Problem A) 3、走迷宫(模板) 4、画图(第六次CCF计算机软件能力认证) 5、山…

Docker 安装 Skywalking以及UI界面

关于Skywalking 在现代分布式系统架构中,应用性能监控(Application Performance Monitoring, APM)扮演着至关重要的角色。本文将聚焦于一款备受瞩目的开源APM工具——Apache Skywalking,通过对其功能特性和工作原理的详细介绍&am…

cocos(困扰了我一晚上的代码)地图适配不同手机屏幕

Creator 版本:3.8.2 目标平台: 微信小游戏 有人反馈我的小游戏没有做屏幕适配。其实我是做了的。但是在不同手机分辨率的情况下。 适配出了问题。然后我改了一晚上的代码终于做好了。 设计的分辨率是960*640.也就是白色区域。 但是大部分手机是…

2024全国水科技大会:【协办单位】山东文远环保科技股份有限公司

山东文远环保科技股份有限公司坐落于千年古城齐国故都--临淄。初始成立于2011年,是淄博市首批国有资本参股的混合改制企业。 公司着力打造环保设备制造、环保工程及服务、环保水务/固废处理/新能源项目投资及运营管理、固废循环经济产业园等四大板块。是一家集投资、…

【spring】@Conditional注解学习

Conditional介绍 Conditional注解用于按照设定的条件进行判断,从而决定是否将某个bean注册到Spring容器中。 Conditional注解是在Spring 4.0版本中引入的,它提供了一种更加灵活的方式来控制bean的创建和注册。在此之前,开发者通常使用Profi…

【网络原理】HTTP 请求 (Request)详解

文章目录 🎍请求格式🎄认识URL🌸query string🌸关于 URL encode 🍀认识 “方法” (method)🌸GET方法🌸POST 方法🌸GET 和 POST 的区别 🌲认识请求 “报头” (header)&…

cocos控制物体移动轨迹

引擎:CocosCreator 3.8.2 思考了很久决定要不要发这票文章。因为毕竟我也是一个新手。但是这个问题真的困扰了我很久。 特意分享给大家。 如图所示有2个方块。他们可以跟着轨迹移动。 这个轨迹箱子总体来说有以下几个规则。 1.只能沿着轨迹移动。 2.上面只能有一…

[ C++ ] STL---string类的模拟实现

目录 string类的成员变量 构造函数 有参构造函数 无参构造函数 析构函数 拷贝构造函数 赋值运算符重载 string类对象的容量操作 string类对象的遍历与访问 [ ] 下标遍历 迭代器遍历 string类对象的增删查改 string类的成员变量 string类底层为动态开辟的字符数组&a…

提升水库大坝安全与效率:现代技术云平台的应用

在我国,水库大坝的数量居世界之首,它们在推动国民经济发展中扮演着不可或缺的角色。然而,要想让这些水利工程充分发挥其价值,不仅需要精准的调度与高效的管理,更重要的是要确保其安全无虞。一旦发生事故,后…

【机器学习】基于变色龙算法优化的BP神经网络分类预测(SSA-BP)

目录 1.原理与思路2.设计与实现3.结果预测4.代码获取 1.原理与思路 【智能算法应用】智能算法优化BP神经网络思路【智能算法】变色龙优化算法(CSA)原理及实现 2.设计与实现 数据集: 数据集样本总数2000 多输入多输出:样本特征24&#xff…

Java中的I/O讲解(超容易理解)(上篇)

如果想观看更多Java内容 可上我的个人主页关注我,地址子逸爱编程-CSDN博客https://blog.csdn.net/a15766649633?spm1000.2115.3001.5343使用工具 IntelliJ IDEA Community Edition 2023.1.4 使用语言 Java8 代码能力快速提升小方法,看完代码自己敲一…

智慧乡村赋能发展:数字乡村推动农村经济社会持续繁荣

目录 一、智慧乡村的内涵与发展意义 二、智慧乡村赋能发展的路径 1、加强信息基础设施建设 2、推进农业生产智能化 3、提升乡村治理现代化水平 4、推动农村产业融合发展 三、智慧乡村发展面临的挑战与对策 四、智慧乡村发展的未来展望 1、技术融合创新将更加深入 2、…

百度智能云+SpringBoot=AI对话【人工智能】

百度智能云SpringBootAI对话【人工智能】 前言版权推荐百度智能云SpringBootAI对话【人工智能】效果演示登录AI对话 项目结构后端开发pom和propertiessql_table和entitydao和mapperservice和implconfig和utilLoginController和ChatController 前端开发css和jslogin.html和chat.…

怎么在Linux系统下Docker部署Excalidraw白板工具并实现无公网IP远程访问?

文章目录 1. 安装Docker2. 使用Docker拉取Excalidraw镜像3. 创建并启动Excalidraw容器4. 本地连接测试5. 公网远程访问本地Excalidraw5.1 内网穿透工具安装5.2 创建远程连接公网地址5.3 使用固定公网地址远程访问 本文主要介绍如何在Ubuntu系统使用Docker部署开源白板工具Excal…

【Linux】实现进度条小程序

个人主页 : zxctscl 如有转载请先通知 文章目录 1. 前言2. 回车和换行3. 缓冲区4. 进度条4.1 倒计时设置4.2 进度条4.2.1 实现简单进度条4.2.2 进度条完善 5. 附进度条代码5.1 Processbar.h5.2 Processbar.c5.3 Main.c5.4 Makefile 1. 前言 在之前已经了解了 【Lin…

C++ list详解及模拟实现

目录 本节目标 1. list的介绍及使用 1.2 list的使用 2.list的模拟实现 1.对list进行初步的实现 2.头插和任意位置的插入 3.pos节点的删除,头删,尾删 4.销毁list和析构函数 5.const迭代器 6.拷贝构造和赋值操作 3.完整代码 本节目标 1. list的…