在java的容器集合中,hashmap的使用频率可以说是相当高的。不过对于hashmap的存(put())以及取(get())的原理可能很多人还不大清楚,今天,我就给大家介绍下它是如何存如何取的

#下面以回答问题的形式来讲解#

**假如有面试官问你,hashmap是如何存数据的,你会怎么回答? **

  1. 我想每个人都知道hashmap是以键值对的方式来存数据的,有些人可能会这么回答:当我们执行put(key, value)函数的时候,以key作为键,value作为值来存,并且如果key相同的话,则新的value会覆盖掉旧的value

  2. 而有些人可能会这么回答:hashmap在存数据的时候是基于hashing的原理,当我们调用put(key,value)方法的时候,其实我们会先对键key调用key.hashcode()方法,根据方法返回的hashcode来找到bucket的位置来存Entry对象。(Entry对象存有key和value)。如下图:(这里没有考虑碰撞)

显然前者和后者的回答,后者的回答还是相对好点的。不过,这可能仅仅只是故事的开始。


**这时面试官可能会问你,如果两个key对象的hashcode相同怎么办? **

  1. 对于不熟悉hashcode()和equals()这两个方法的人来说,他可能会直接说,因为hashcode相同,那么两个对象是同一个对象,进而新的value覆盖掉旧的value。如果你这样回答,后果你懂 。(当然可能面试会提醒你或直接问你别的问题了)。

  2. 有些人则会回答,由于hashcode相同,那么它们对应的bucket显然也是相同的,这个时候就会产生所谓的碰撞(hashmap的底层存储结构是 数组+链表)。每个bucket索引对应一个链表,这个时候系统就会找到对应的链表,并在链表的尾部加上这个Entry对象,如下图:(图画的有点丑,哈哈)

  1. 这个时候跑出来个第三者,自豪着补充了一句:根据hashcode找到对应的bucket之后,还会在对应的链表逐一检查这个链表里有没存在相同的key对象,这个时候是通过equals这个方法来对比的。如果有,者用新的value取代旧的value。如果没有,则向楼上说的,在链表的尾部加上这个新的Entry对象。

  • 这个时候,hashmap的put原理讲解就告一段落了。下面说说获取get(key)原理
  • 其实get原理和put原理是差不多的,一个逆向的过程。
  1. 当我们调用get(key)的时候,会调用key的hashcode方法获得hashcode.
  2. 根据hashcode获取相应的bucket。
  3. 由于一个bucket对应的链表中可能存有多个Entry,这个时候会调用key的equals方法来找到对应的Entry
  4. 最后把值返回(这句好像是废话....但我还是想说下)。

继续涨知识......

和其他容器一样,当我们没有指定大小直接new一个hashmap的时候

系统会自动给我们初始化一个数值。如果我们在存数据的过程中,大小超过了负载因子定义的容量怎么办?

  • 这里先给大家解释下 负载因子:负载因子(load factor,假设大小为n)就是当一个map填满了n倍的bucket的时候,hashmap就会进行扩容。

  • 其实当一个map被填满到75%的时候(默认的负载因子大小是0.75),它就会进行扩容,创建一个大小是原理两倍的bucket数组,并且将原理的数据存放到新的数组里。


大家都知道,当Map在扩容新的数组并且移动数据的时候,都是比较消耗时间和内存的,如果我们事先能预测到我们到存的数据的大致大小的话,我们就可以新创建hashmap的时候指定大小,这样,可以大小减少扩容带来的消耗。

  • 这里可能大家有一些疑问,例如为啥默认的负载因子大小是0.75呢(看有些人在讨论这个问题)。对于这个我觉得可能是通过大量的数据测出来的(还没有去百度看别人的解答,仅代表个人观点,欢迎你们的解答)
  • 这里在给大家解释以下负载因子的作用(可能有些人还不知道负载因子的干啥用的)
  1. 负载因子越大,数组要被填满时,元素就会越多,元素越多,冲突的几率就会越大,一个链表存的元素也会越多,查询的时候就会越慢。但是,此时空间的利用率更高了----空间换时间
  2. 负载因此越小,数组要被填满时,元素就会越少,冲突也会也少,一个链表的元素也会越少,查询的时候也就越快。但是,空间的利用率低了-----时间换空间。

如果你习惯在微信公众号看技术文章
想要获取更多资源的同学
欢迎关注我的公众号:苦逼的码农
每天向你推送 各种视频资源,电子书、 技术文章以及
和面试有关的 算法专题 每日一题

HashMapd的存取原理你知道多少的更多相关文章

  1. DMA 内存存取原理

    DMA直接内存存取原理 DMADMA直接内存存取原理是指外部设备不通过CPU而直接与系统内存交换数据的接口技术. 要把外设的数据读入内存或把内存的数据传送到外设,一般都要通过CPU控制完成,如CPU程 ...

  2. HashMap原理(二) 扩容机制及存取原理

    我们在上一个章节<HashMap原理(一) 概念和底层架构>中讲解了HashMap的存储数据结构以及常用的概念及变量,包括capacity容量,threshold变量和loadFactor ...

  3. HashMap存取原理之JDK8

    前言 哈希表(hash table)也叫散列表,是一种非常重要的数据结构 应用场景之一:缓存技术(比如memcached的核心其实就是在内存中维护一张大的哈希表) 目录 一.哈希表 二.hashmap ...

  4. DMA直接内存存取原理

    DMA是指外部设备不通过CPU而直接与系统内存交换数据的接口技术. 要把外设的数据读入内存或把内存的数据传送到外设,一般都要通过CPU控制完成,如CPU程序查询或中断方式.利用中断进行数据传送,可以大 ...

  5. 【转】MySQL索引背后的数据结构及算法原理

    摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BT ...

  6. [转]MySQL索引背后的数据结构及算法原理

    摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BT ...

  7. MySQL索引背后的数据结构及算法原理【转】

    本文来自:张洋的MySQL索引背后的数据结构及算法原理 摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持 ...

  8. MySQL索引背后的数据结构及算法原理

    摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BT ...

  9. [纯干货] MySQL索引背后的数据结构及算法原理

    摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BT ...

随机推荐

  1. python3安装lxmlpipinstall安装失败解决办法

    最近在学习python爬虫技术,lxml模块拥有很强大的获取元素功能,但是安装时总超时报错,如下解决办法 选择好python版本→注意pip版本→下载对应lxml.whl→键入对应的字符串→bingo ...

  2. Codechef April Challenge 2019 游记

    Codechef April Challenge 2019 游记 Subtree Removal 题目大意: 一棵\(n(n\le10^5)\)个结点的有根树,每个结点有一个权值\(w_i(|w_i\ ...

  3. ie低版本内核事件兼容问题(事件绑定,绑定事件自动执行,文档模式问题)

    问题情况 搜狗等,兼容模式下,以前前端写的点击事件的代码没有, 后来一看是因为兼容模式为9,导致点击事件失效 解决办法,步骤 1,处理绑定事件兼容问题 ie低版本绑定事件只支持attactevent, ...

  4. Kafka 安装配置

    1. 下载安装kafka 下载地址:http://apache.fayea.com/kafka/ 解压安装包 tar zxvf kafka_版本号.tgz 2. 配置 修改kafka的config/s ...

  5. Catalan 数列的性质及其应用(转载)

    转自:http://lanqi.org/skills/10939/ 卡特兰数 — 计数的映射方法的伟大胜利 发表于2015年11月8日由意琦行 卡特兰(Catalan)数来源于卡特兰解决凸$n+2$边 ...

  6. jquery for循环

    第一种: for(var i=0,len=$len.length; i<len; i++){//alert($len.eq(i).html());$zongshu=$zongshu+$len.e ...

  7. Spring + SpringMVC + Mybatis项目中redis的配置及使用

    maven文件 <!-- redis --> <dependency> <groupId>redis.clients</groupId> <art ...

  8. [Educational Round 59][Codeforces 1107G. Vasya and Maximum Profit]

    咸鱼了好久...出来冒个泡_(:з」∠)_ 题目连接:1107G - Vasya and Maximum Profit 题目大意:给出\(n,a\)以及长度为\(n\)的数组\(c_i\)和长度为\( ...

  9. 34 文件地理数据库(GDB)变文件夹了怎么办

    我们都知道文件地理数据库(GDB)是ArcGIS软件特有的格式,有其独特的设计之处,在文件资源管理器中显示为.gdb的文件夹,但是里面的文件却看不明白,而且将gdb文件夹在Windows资源管理器中直 ...

  10. input type=passoord 密码框的明密文(显示和隐藏) 显示

    最近在写一个新的项目,从头开始写,所以就要从注册登录开始做起.以前写登录注册模块的时候,无外乎给input框一个type=”password”就可以了,近期因为要涉及到显示隐藏状态的切换. 样式代码如 ...