##HashMap1.8和1.8之前的源码差别很大

目录

简介

数据结构

类结构

属性

构造方法

增加

1.HashMap简介

HashMap基于哈希表的Map接口实现,是以key-value存储形式存在。(除了不同步和允许使用 null 之外,HashMap 类与 Hashtable 大致相同。)

HashMap 的实现不是同步的,这意味着它不是线程安全的。它的key、value都可以为null。此外,HashMap中的映射不是有序的。在 JDK1.8 中,HashMap 是由 数组+链表+红黑树构成,新增了红黑树作为底层数据结构,结构变得复杂了,但是效率也变的更高效。

1.2 HashMap数据结构

在 JDK1.8 中,HashMap 是由 数组+链表+红黑树构成,新增了红黑树作为底层数据结构,结构变得复杂了,但是效率也变的更高效。当一个值中要存储到Map的时候会根据Key的值来计算出他的

hash,通过哈希来确认到数组的位置,如果发生哈希碰撞就以链表的形式存储 在Object源码分析中解释过,但是这样如果链表过长来的话,HashMap会把这个链表转换成红黑树来存储。

来看一下HashMap的存储结构

但是这样的话问题来了,HashMap为什么要使用红黑树呢,这样结构的话不是更麻烦了吗??

这个问题我也没有想过,其实很多在看的时候只会在乎红黑树的实现而忽略到了为什么要使用的这个问题,我也是在写本文的时候突发疑惑。参考了网上的例子,同时也解释了为什么阀值为8:

因为Map中桶的元素初始化是链表保存的,其查找性能是O(n),而树结构能将查找性能提升到O(log(n))。当链表长度很小的时候,即使遍历,速度也非常快,但是当链表长度不断变长,肯定会对查询性能有一定的影响,所以才需要转成树。至于为什么阈值是8,我想,去源码中找寻答案应该是最可靠的途径。

参考地址:https://dwz.cn/nPFXmXwJ

2.类结构

我们来看一下类结构

在阅读源码的时候一直有个问题很困惑就是HashMap已经继承了AbstractMap而AbstractMap类实现了Map接口,那为什么HashMap还要在实现Map接口呢?同样在ArrayList中LinkedList中都是这种结构。

据 java 集合框架的创始人Josh Bloch描述,这样的写法是一个失误。在java集合框架中,类似这样的写法很多,最开始写java集合框架的时候,他认为这样写,在某些地方可能是有价值的,直到他意识到错了。显然的,JDK的维护者,后来不认为这个小小的失误值得去修改,所以就这样存在下来了。

  • Cloneable 空接口,表示可以克隆
  • Serializable 序列化
  • AbstractMap 提供Map实现接口

3.属性

初始化容量(必须是二的n次幂)

集合最大容量(必须是二的幂)

负载因子,默认的0.75

当链表的值超过8则会转红黑树(1.8新增)

当链表的值小于6则会从红黑树转回链表

当Map里面的数量超过这个值时,表中的桶才能进行树形化 ,否则桶内元素太多时会扩容,而不是树形化 为了避免进行扩容、树形化选择的冲突,这个值不能小于 4 * TREEIFY_THRESHOLD

table用来初始化(必须是二的n次幂)

用来存放缓存

HashMap中存储的数量

用来记录HashMap的修改次数

用来调整大小下一个容量的值计算方式为(容量*负载因子)

哈希表的加载因子

重点属性

  • table在JDK1.8中我们了解到HashMap是由数组加链表加红黑树来组成的结构其中table就是HashMap中的数组
  • size为HashMap中K-V的实时数量
  • loadFactor加载因子,是用来衡量 HashMap 满的程度,计算HashMap的实时加载因子的方法为:size/capacity,而不是占用桶的数量去除以capacity。capacity 是桶的数量,也就是 table 的长度length。
  • threshold计算公式:capacity * loadFactor。这个值是当前已占用数组长度的最大值。过这个数目就重新resize(扩容),扩容后的 HashMap 容量是之前容量的两倍

4.构造方法

开始看构造方法。

4.1 HashMap()

构造一个空的 HashMap ,默认初始容量(16)和默认负载因子(0.75)。

4.2 HashMap(int initialCapacity)

构造一个空的 HashMap具有指定的初始容量和默认负载因子(0.75)。

4.3 HashMap(int initialCapacity, float loadFactor)

构造一个空的 HashMap具有指定的初始容量和负载因子。我们来分析一下。

最后调用了tableSizeFor,来看一下方法实现:

5.增加

现在我们开始分析put()方法

我们可以看到put调用的是putVal来进行数据插入,但是要注意到key在这里执行了一下hash()方法,来看一下Hash方法是如何实现的。

从上面可以得知HashMap是支持Key为空的,而HashTable是直接用过Key来获取HashCode所以key为空会抛异常其实上面就已经解释了为什么HashMap的长度为什么要是2的幂因为HashMap 使用的方法很巧妙,它通过 hash & (table.length -1)来得到该对象的保存位,前面说过 HashMap 底层数组的长度总是2的n次方,这是HashMap在速度上的优化。当 length 总是2的n次方时,hash & (length-1)运算等价于对 length 取模,也就是 hash%length,但是&比%具有更高的效率。比如 n % 32 = n & (32 -1)。

现在看putVal()方法,看看它到底做了什么。

主要参数:

  • hash key的hash值
  • key 原始Key
  • value 要存放的值
  • onlyIfAbsent 如果true代表不更改现有的值
  • evict 如果为false表示table为创建状态

完整源码分析,放图片的话会太长了,所以就截取了一下分为两部。


最后:

如果看完这篇文章觉得对你还有那么一点启发的话烦请关注+转发一波让更多的人看到哦,笔者也会定期更新技术干货和大家一起学习交流哦!笔者也整理收集了一份笔记和讲解视频。需要的小伙伴可以点击此处:https://docs.qq.com/doc/DWFdDS3JZZ1F4TmZU获取下载!

最后

本人也收藏了一份Java面试核心知识点来应付面试,借着这次机会可以免费送给我的读者朋友们

目录:

Java面试核心知识点

一共有30个专题,足够读者朋友们应付面试啦,也节省朋友们去到处搜刮资料自己整理的时间!有需要的朋友戳这里即可免费获取

Java面试核心知识点

已经有读者朋友靠着这一份Java面试知识点指导拿到不错的offer了,各位读者朋友们快来免费获取吧

qq.com/doc/DSmxTbFJ1cmN1R2dB)**

[外链图片转存中…(img-zykIezRL-1623615974749)]

Java面试核心知识点

已经有读者朋友靠着这一份Java面试知识点指导拿到不错的offer了,各位读者朋友们快来免费获取吧

[外链图片转存中…(img-ur3qxBlL-1623615974750)]

史上超级详细:HashMap源码分析,你了解到源码的魅力了嘛相关推荐

  1. ESP8266 Non-OS SDK 开发之旅 基础篇① 初识 Non-OS SDK,史上超级详细手把手教小白20分钟快速搭建SDK软件开发环境,完成第一个例子Hello World!

    文章目录 1.前言 2. SDK概述 2.1 SDK使用流程 2.2 ESP8266 HDK -- 硬件开发工具 2.3 ESP8266 SDK -- 软件开发工具包 2.3.1 Non-OS SDK ...

  2. 史上超级详细:java图片转二进制

    阿里的人才画像 其实最近两年自己一直在做面试官,也面试过很多优秀的人,心里大概有一个标准,知道什么样的人才是我们想要的人. 但是这个标准我一直都没有仔细的去思考过,刚好最近有时间,我好好的思考了一下, ...

  3. android项目实战博学谷源码_Vue框架:史上最详细的Vue实战项目之喵喵电影(视频+源码)...

    Vue是web前端中重要的框架之一,与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计,Vue 的核心库只关注视图层,并且非常容易学习,非常容易与其它库或已有项目整合.所以,对于web前端开 ...

  4. Storm源码分析之四: Trident源码分析

    Storm源码分析之四: Trident源码分析 @(STORM)[storm] Storm源码分析之四 Trident源码分析 一概述 0小结 1简介 2关键类 1Spout的创建 2spout的消 ...

  5. android qq消息数 拖拽动画,史上最详细仿QQ未读消息拖拽粘性效果的实现

    好久没写文章了,前段时间由于项目代码重构忙了一段时间,现在终于有点时间了就为大家带来一篇关于动画学习的自定义View:类似QQ消息拖拽的效果. 其实QQ当时更新的时候我还没注意到这个小红点是可以拖拽的 ...

  6. 史上最详细sql注入wp

    文章目录 sql注入wp(史上最详细) 前言 什么是SQL注入? SQL注入的原理 常见的注入方式 常见绕过技巧 常见防控SQL注入的方法 手工查询语句 Basic Challenges Less-1 ...

  7. 史上最详细全中文 Cisco 3560交换机使用手册

    史上最详细全中文 Cisco 3560交换机使用手册 (末尾送交换机安全技术) 目 录 CISCO Catalyst 3560-E系列交换机的功能应用及安全解决方案 3 一.Cisco? Cataly ...

  8. 史上最详细网络基础知识

    网络技术的基本原理: 1. 网络层次划分 2. OSI七层网络模型 3. IP地址 4. 子网掩码及网络划分 5. ARP/RARP协议 6. 路由选择协议 7. TCP/IP协议 8. UDP协议 ...

  9. RISC-V AI芯片Celerity史上最详细解读(上)(附开源地址)

    RISC-V AI芯片Celerity史上最详细解读(上)(附开源地址) (本文包括Celerity中二值化神经网络的介绍) 作者 陈巍,资深芯片专家,人工智能算法-硬件协同设计专家. 在Hot Ch ...

最新文章

  1. LeetCode简单题之检查整数及其两倍数是否存在
  2. android media player setlooping,Android Mediaplayer-一次播放铃声
  3. 跨链Cosmos(12) Cosmos插件
  4. Opencv实战之图像的基本操作:这效果出来惊艳了众人(附代码解析)
  5. sql的加减乘除运算_小白学sql(一)
  6. duilib中界面的布局方式
  7. matlab连续型随机变量,matlab连续型随机变量的分布.doc
  8. 计算机补丁的概念,补丁是什么意思?网上说的打补丁什么意思
  9. 浅说项目管理中的Action以及3W1P原则
  10. 对抗样本:知其然,知其所以然
  11. php 回车符替换,php怎么替换回车符
  12. concat函数_《MySQL 入门教程》第15篇MySQL常用函数之字符函数
  13. 《漫画机器学习入门》总结
  14. Python Spider 的总结
  15. Theory for the information-based decomposition of stock price
  16. 如何做召回dssm,fm,Mind,youtube等模型
  17. 51单片机之蜂鸣器为什么不响
  18. pythonbmi代码_python用代码实现体质指数BMI测试功能
  19. 菜鸟的数学建模之路(六):层次分析法
  20. 在WINDOWS 下删除EISA配置的隐藏分区

热门文章

  1. opencv---JPEG图像质量检测代码
  2. asyncio.Protocol socket 断线重连
  3. subprocess installed post-installation script returned error exit status 1
  4. 安卓屏幕分辨率及UI尺寸详解
  5. 交叉编译并移植opencv3.0.0到arm板
  6. php传输html乱码解决
  7. EPON与GPON的应用与区别
  8. 动词ing形式的5种用法_课后文档:英语语法思维第7课动词的5个形式的用法
  9. matlab一句一句调试,matlab程序怎样调试和运行
  10. ip协议分析实验报告_入门工业通讯之EtherNet/IP协议分析