jdk1.7 和 1.8 大致相同但还是有区别,主要是数据结构的区别,1.7 为数组+链表;1.8 为数组+链表+红黑树

关键知识点

  • 加载因子:装填因子,目的是何时对 map 进行扩容,默认是 0.75 即容量达到 75% 时对 map 扩容,原数组扩大为两倍长度
  • 扩容阈值,根据数组长度和加载因子相乘得到的值,达到这个值就会扩容
  • hash 算法:也叫hash函数,hash运算,指的是把 key 换算成数组的下标的算法(hashCode+数组长度+一系列右移和异或运算)
  • hash 冲突:不同的 key 经过 hash 运算后得到了相同的数组下标(这时数组元素不止一个,解决的方式很多,java 采用 链式寻址法 也就是链表来解决)
  • 数组长度默认是 16,且长度只会是 2 的指数个数(初始化指定的长度实际会是当前值最接近2的指数的值,比如指定为3,实际会是8)
  • new HashMap() 时不会初始化数组,在 put 的时候才会初始化,具体是 put 时判断数组是否为空,如果为空再创建长度为 16 的数组
  • 数组的元素是链表,这个说法不是特别准确,只是说可以这样理解,准确的说法是数组的元素是链表的头节点

jdk 1.7 put 过程

  • 判断数组(table)是否为空,如果为空就先创建数组(put 才初始化数组,扩容阈值等也是 put 时确定,懒加载思维)

    • 如果不指定长度,默认就是16
    • 如果指定长度,并不是创建指定长度的数组,而是根据指定的长度得到最接近 2 的指数值,把这个值作为数组长度来初始化
  • hash 运算得到数组下标 i
    • 先得到 hashCode,hashCode 远远不够,还需要别的运算才能满足当前数组的下标范围
    • 把 hashCode 多次右移和异或运算得到一个值(hash 值)
    • 把 hash 值和数组长度-1做与运算(i = h & length-1),因为要保证这里的与运算能正确得到符合数组的下标,所以数组的长度必须是 2 的指数
  • 把元素放入数组下标i的位置,分两种情况:当前位置有值和没有值
    • 如果有值,table[i] 就是个链表,遍历这个链表,也会有两种情况,key 重复和不重复(使用 equals 比较),如果 key 重复就覆盖,返回原来的值,流程结束
    • 如果没有值或者 key 不重复,继续往下走,执行新增逻辑,addEntry 方法
  • 新增元素 addEntry 方法逻辑(如果 table[i] 为空,table[i] 就放当前 entry,如果不为空那就是个链表,头插法维护链表)
    • 如果 size + 1 大于扩容阈值(长度*负载因子)会先进行扩容,table 长度变为原来的 2 倍,扩容方法是resize(2 * teble.length)
    • 如果 size + 1 不大于扩容阈值,就把 key-value 构建成一个节点(Entry 对象)采用头插法维护 table[i] 的链表
    • size++,返回 null,流程结束

jdk1.7 扩容

创建一个新的 table, 长度变为原来的 table 的两倍,首先把原来 table 的元素先全部拷贝到新的 table 中,拷贝的的过程中不是简单复制数组,而是重新 根据新的 table 长度进行哈希运算,把原来的元素放进新的 table 中,这样有个显著的特点,因为 table 变成了,所以 hash 运算得到的下标和原来的下标不一样,这样就会更少的发生 hash 冲突,从而把链表的长度变短

jdk1.7 get

只要明白 put 就应该能明白 get,因为 put 会先找一遍,如果没有再新增 entry。get 大概逻辑:

  • 根据 key 得到 hashCode
  • 再经过 hash 函数(多次右移+异或)得到 hash
  • 根据 hash 和 数组长度-1(数组下标)进行与运算得到数组下标
  • 再用 eauals 比较链表的 key,如果相等就获取返回

java HashMap 原理的更多相关文章

  1. Java:HashMap原理与设计缘由

    前言 Java中使用最多的数据结构基本就是ArrayList和HashMap,HashMap的原理也常常出现在各种面试题中,本文就HashMap的设计与设计缘由作出一一讲解,并解答面试常见的一些问题. ...

  2. Java HashMap原理

    HashMap存储结构 HashMap中数据的存储是由数组与链表一起实现的 数组寻址非常容易,其时间复杂度为O(1),但是当要插入或删除数据时,时间复杂度就会变为O(n).链表插入和删除操作的内存复杂 ...

  3. java - HashMap原理及实现 (转)

    众所周知,HashMap是一个用于存储Key-Value键值对的集合,每一个键值对也叫做Entry.这些个键值对(Entry)分散存储在一个数组当中,这个数组就是HashMap的主干. HashMap ...

  4. HashMap的原理与实 无锁队列的实现Java HashMap的死循环 red black tree

    http://www.cnblogs.com/fornever/archive/2011/12/02/2270692.html https://zh.wikipedia.org/wiki/%E7%BA ...

  5. Java HashMap工作原理及实现

    Java HashMap工作原理及实现 2016/03/20 | 分类: 基础技术 | 0 条评论 | 标签: HASHMAP 分享到:3 原文出处: Yikun 1. 概述 从本文你可以学习到: 什 ...

  6. Java基础-hashMap原理剖析

    Java基础-hashMap原理剖析 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.   一.什么是哈希(Hash) 答:Hash就是散列,即把对象打散.举个例子,有100000条数 ...

  7. Hash算法及java HashMap底层实现原理理解(含jdk 1.7以及jdk 1.8)

    现在很多公司面试都喜欢问java的HashMap原理,特在此整理相关原理及实现,主要还是因为很多开发集合框架都不甚理解,更不要说各种其他数据结构了,所以造成面子造飞机,进去拧螺丝. 1.哈希表结构的优 ...

  8. Java HashMap实现原理分析

    参考链接:https://www.cnblogs.com/xiarongjin/p/8310011.html 1. HashMap的数据结构 数据结构中有数组和链表来实现对数据的存储,但这两者基本上是 ...

  9. java中HashMap原理?

    参考:https://www.cnblogs.com/yuanblog/p/4441017.html(推荐) https://blog.csdn.net/a745233700/article/deta ...

  10. Java HashMap工作原理:不仅仅是HashMap

    前言: 几乎所有java程序员都用过hashMap,但会用不一定会说. 近年来hashMap是非常常见的面试题,如何为自己的回答加分?需要从理解开始. "你用过hashMap吗?" ...

随机推荐

  1. CTFshow刷题记录

    整理的一些ctf题目 WEB题 ctfshow 年CTF 除夕 题目要求通过get传入year参数然后进行判断是否成立,成立就返回flag 这里可以用科学计数法表示通过get传入year=2.022e ...

  2. wixtoolset visualstudio 2017打包流程(1)

    第一步: 使用wix提供的 heat.exe 工具生成后缀为 wsx 的配置文件.   heat.exe dir ".\binr" -dr INSTALLFOLDER -cg Pr ...

  3. @Slf4j -- lombok.extern.slf4j.Slf4j;

    @Log4j:注解在类上:为类提供一个 属性名为log 的 log4j 日志对像 package com.atguigu.springcloud.controller; import com.atgu ...

  4. 高效字符串匹配算法——BM 算法详解(C++)

    定义 BM 算法是由 Boyer 和 Moore 两人提出的一种高效的字符串匹配算法,被认为是一种亚线性算法(即平均的时间复杂度低于线性级别),其时间效率在一般情况下甚至比 KMP 还要快 3 ~ 5 ...

  5. C语言知识补充 --来自菜鸟教程的指针复习

    1.system 打开其他应用 1.指针演练  C 指针. 正如您所知道的,每一个变量都有一个内存位置,每一个内存位置都定义了可使用 & 运算符访问的地址,它表示了在内存中的一个地址. #in ...

  6. 中南大学CSU2022-2023级C语言期中考试机试答案

    卡在出线概率了.40%,没想到遍历时反了,我去. 1.时钟加法 1 #include<stdio.h> 2 3 #include<string.h> 4 5 #include& ...

  7. 大曝光!从RabbitMQ平滑迁移至Kafka架构设计方案!

    历史原因,公司存在多个 MQ 同时使用的问题,我们中间件团队在去年下半年开始支持对 Kafka 和 Rabbit 能力的进行封装,初步能够完全支撑业务团队使用. 鉴于在之前已经基本完全实施 Kafka ...

  8. 关于HTML5中Video标签播放问题

    PS:官网首页视频IOS与安卓都可播放代码: <video width="100%" height="auto" type="video/mp4 ...

  9. Infinity 和 -Infinity

    认识 Infinity 在 JavaScript 中超出 1.797693134862315E+308 的数值即为 Infinity,小于 -1.797693134862316E+308 的数值为无穷 ...

  10. PE头结构解析(代码实现)

    PE头结构解析(代码实现) 图表实现在:https://www.cnblogs.com/juicyhumberger/articles/17064764.html #include "std ...