【夯实Java基础】(五)轻松掌握 HashMap 源码

简介: 【夯实Java基础】(五)轻松掌握 HashMap 源码

文章目录


引子

图解 HashMap 的数据结构

详细分析 HashMap 源码的代码


引子


计算机中如果存储数据的话,我们该怎么办?

数据在计算机中存储的一个方式/结构(数据结构)

如果我们对 HashMap 底层的数据结构都搞清楚,那应该能有助于我们看懂源码。


数据结构?? 数组、链表、树形、图形


20191205144639112.png


图解 HashMap 的数据结构


Key,value---------------------> HashMap 的数据结构应该比较吊

我们可以大胆的猜测 HashMap 应该是将 数组和链表的优势结合起来

数组+链表的形式 -----------> HashMap 的数据结构 jdk1.8 红黑树


20191205150939986.png


紫色部分即代表哈希表本身(其实是一个数组),数组的每个元素都是一个单链表的头节点,链表是用来解决hash地址冲突的,如果不同的key映射到了数组的同一位置处,就将其放入单链表中保存。


详细分析 HashMap 源码的代码


数组的表示:Node table[]


20191205151753799.png


默认初始容量为16


20191205151941173.png


20191205152121843.png


数组的大小可能会不够用 扩大


问题是? 什么时候进行扩大? 数组16已经用到16的时候再扩大呗?


从感性层面和理性层面来看,我们可以看到 16*0.75=12 数组扩大的一个标准


Java是面向对象的,从上图的双向链表来看,我们可以猜测用代码实现双向链表大概如下:

class Node{
    Object data;
    Node prev;
    Node next;
  }


这在LinkedList源码中得到验证。


20191205145456794.png


链表的长度不能无限大,怎么叫做一个上限?

链表和红黑树之间的转变----------> 相对适合它们各自效率的一个节点


20191205153103285.png


20191205153223509.png


记录一下数组使用格子的数量


size=0 size++


20191205153454242.png


来了一个 key,value 组成了 Node 节点后, 这个节点到底该何去何从?


数组的大小 16

Random.next(16) 0-15

如果落点的算法仅仅是这样的话,就未免太low了

数组的 16 个位置要充分利用其中的 12 个


----------------------------->


生成出一个算法 hash 算法

(1) Int

Key,value -----------------------> key Object ------------------>key.hashCode()

32434535(一个哈希值) hash


(2) 0-15 数组的大小范围

Hash%16 0-15


(3) 尽可能充分利用数组的每一个位置


20191205164232671.png


到了这里,我对 Node 节点的属性都已了然于心。


继续看源码,数组先进行了初始化:

Node[] table = new Node[16];

Resize() 功能 是可以对数组进行初始化操作


20191205164755411.png


把数组的默认大小 和 16*0.75


20191205164936673.png


threshold = 12


20191205165059326.png


(1) 数组原本的位置为空

(2) 数组原本的位置不为空,且下面是链表结构


20191205184014869.png


(3) 数组原本的位置不为空,且下面是红黑树结构


20191205173701919.png


n-1{15} & hash <------------------------ > hash % n{16} 0-15


20191205183055274.png


Key.hashCode() 高16位和16位进行异或运算,这样结果才能尽可能不同


20191205183240834.png


20191205153454242 (1).png


Resize() 数组的初始化操作 数组的扩容的操作


20191205185226386.png


Double 2 倍 为什么是两倍进行扩大数组呢??


20191205190854523.png


16 ------> 32

12 ------> 24


20191205191515940.png


为什么下面还要有代码呢??


因为节点不要总是赖在原来的数组中,也要往新的数组中移动。(重新散列)


老数组进行判断,如果下面是空,进行重新hash 得到一个新的位置


20191205191757161.png


如果为0,保持在原来的位置不动

如果不为0,加上原来的capacity

Hash n-1


1.8 中实现了

TreeNode Parent left right

Treelfy_Threshold 8 超过了这个8 链表----红黑树

Put 判断链表的长度


目录
相关文章
|
5天前
|
运维 Java
Java版HIS系统 云HIS系统 云HIS源码 结构简洁、代码规范易阅读
云HIS系统分为两个大的系统,一个是基层卫生健康云综合管理系统,另一个是基层卫生健康云业务系统。基层卫生健康云综合管理系统由运营商、开发商和监管机构使用,用来进行运营管理、运维管理和综合监管。基层卫生健康云业务系统由基层医院使用,用来支撑医院各类业务运转。
25 5
|
22小时前
|
设计模式 算法 Java
[设计模式Java实现附plantuml源码~行为型]定义算法的框架——模板方法模式
[设计模式Java实现附plantuml源码~行为型]定义算法的框架——模板方法模式
|
22小时前
|
设计模式 JavaScript Java
[设计模式Java实现附plantuml源码~行为型] 对象状态及其转换——状态模式
[设计模式Java实现附plantuml源码~行为型] 对象状态及其转换——状态模式
|
1天前
|
设计模式 存储 JavaScript
[设计模式Java实现附plantuml源码~创建型] 多态工厂的实现——工厂方法模式
[设计模式Java实现附plantuml源码~创建型] 多态工厂的实现——工厂方法模式
|
1天前
|
设计模式 Java Go
[设计模式Java实现附plantuml源码~创建型] 集中式工厂的实现~简单工厂模式
[设计模式Java实现附plantuml源码~创建型] 集中式工厂的实现~简单工厂模式
|
1天前
|
Java 调度
Java面试必考题之线程的生命周期,结合源码,透彻讲解!
Java面试必考题之线程的生命周期,结合源码,透彻讲解!
8 1
|
5天前
|
JavaScript Java 测试技术
基于Java的电影评论系统的设计与实现(源码+lw+部署文档+讲解等)
基于Java的电影评论系统的设计与实现(源码+lw+部署文档+讲解等)
21 0
|
5天前
|
JavaScript Java 测试技术
基于Java的在线日语培训平台的设计与实现(源码+lw+部署文档+讲解等)
基于Java的在线日语培训平台的设计与实现(源码+lw+部署文档+讲解等)
23 0
|
5天前
|
JavaScript Java 测试技术
基于Java的同城蔬菜配送管理系统的设计与实现(源码+lw+部署文档+讲解等)
基于Java的同城蔬菜配送管理系统的设计与实现(源码+lw+部署文档+讲解等)
11 0
|
5天前
|
JavaScript Java 测试技术
基于Java的心理预约咨询管理系统的设计与实现(源码+lw+部署文档+讲解等)
基于Java的心理预约咨询管理系统的设计与实现(源码+lw+部署文档+讲解等)
22 0
基于Java的心理预约咨询管理系统的设计与实现(源码+lw+部署文档+讲解等)