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. 安装postcss-px-to-viewport 配置postcss.config.js 报错Error: true is not a PostCSS plugin

    因项目需要,用户突然要坚持小屏幕也要观看大屏代码,临时解决方案是加了一个postcss-px-to-viewport ,安装过程中报错Error: true is not a PostCSS plug ...

  2. 迁移学习(ADDA)《Adversarial Discriminative Domain Adaptation》

    论文信息 论文标题:Adversarial Discriminative Domain Adaptation论文作者:Eric Tzeng, Judy Hoffman, Kate Saenko, Tr ...

  3. 异常概念&异常体系-异常分类

    异常概念&异常体系 异常,就是不正常的意思.在生活中:医生说,你的身体某个部分有异常,该部位和正常相比有点不同,该部位的功能将受影响,在程序中的意思就是: 异常:指的是程序在执行过程中,出现的 ...

  4. Java8Stream流

    Stream流呢,以前我也有所了解,像一些面试题中也出现过,Java8的新特性,有一块就是这个Stream操作集合,而且在看一些项目中也使用的比较多.但总感觉自己学的一知半解,所以今天打算系统的过一下 ...

  5. Java CompletableFuture 异步超时实现探索

    作者:京东科技 张天赐 前言 JDK 8 是一次重大的版本升级,新增了非常多的特性,其中之一便是 CompletableFuture.自此从 JDK 层面真正意义上的支持了基于事件的异步编程范式,弥补 ...

  6. day05-SpringMVC底层机制简单实现-01

    SpringMVC底层机制简单实现-01 主要完成:核心分发控制器+Controller和Service注入容器+对象自动装配+控制器方法获取参数+视图解析+返回JSON格式数据 1.搭建开发环境 创 ...

  7. 【一句话】@Configuration和@Component的区别

    首先一句话: @Configuration修饰的类会被Cglib动态代理,@Component不会. 详细: Cglib动态代理生成当前对象的子类Class,并对方法拦截,多次调用@Bean方法时直接 ...

  8. Android 初代 K-V 存储框架 SharedPreferences,旧时代的余晖?

    本文已收录到  AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 提问. 前言 大家好,我是小彭. SharedPreferences 是 Android 平台上轻量级的 K-V ...

  9. 交叉熵损失CrossEntropyLoss

    在各种深度学习框架中,我们最常用的损失函数就是交叉熵,熵是用来描述一个系统的混乱程度,通过交叉熵我们就能够确定预测数据与真实数据的相近程度.交叉熵越小,表示数据越接近真实样本. 1 分类任务的损失计算 ...

  10. JZOJ 1967.【2011集训队出题】聪聪可可

    题目 [2011集训队出题]聪聪可可 思路 看看做做 阴阳 这道题 极力推荐 自从做了这道题后,这些题就变成秒切的题了 很容易想到求节点到分治中心的距离,然后 \(\bmod 3\) 那么在求根节点一 ...