对HashMap的思考及手写实现

简介:

HashMap是Java中常用的集合,而且HashMap的一些思想,对于我们平时解决业务上的一些问题,在思路上有帮助,基于此,本篇博客将分析HashMap底层设计思想,并手写一个迷你版的HashMap!

113f07deff4ef2c4bbdc88d82517610971bca46b

对HashMap的思考

9fa71e3820033292d7dc50e4096b8d08e6c05979

HashMap底层数据结构

第一,如图所示,HashMap有3个要素:hash函数+数组+单链表

通过写一个迷你版的HashMap来深刻理解

定义接口

3049e2388c68198a5cabc58c4bb8150eafed5d65

接口

定义一个接口,对外暴露快速存取的方法。

注意MyMap接口内部定义了一个内部接口Entry。

接口实现

3df1edd11dbd6abc1120ca7099f98b05b5aa2420

MyHashMap定义

HashMap的要素之一,就是数组,自然在这里,我们要定义数组,数组的初始化大小,还要考虑扩容的阀值。

看MyHashMap的构造

073615f0c1e6eb6db4cbabfa909e726c7918657d

构造方法

构造方法有什么好说的呢?

仔细观察下,你会发现,其实这里使用到了“门面模式”。这里的2个构造方法其实指向的是同一个,但是对外却暴露了2个“门面”!

Entry

cf4a1cbf925b9a3502e7fa392b91ae70b8961f25

Entry

HashMap的要素之一,单链表的体现就在这里!

看put如何实现

9018909d621dacd850ed7826b8ee520bf5daa89c

put

第一,要考虑是否扩容?

HashMap中的Entry的数量(数组以及单链表中的所有Entry)是否达到阀值?

第二,如果扩容,意味着新生成一个Entry[],不仅如此还得重新散列。

第三,要根据Key计算出在Entry[]中的位置,定位后,如果Entry[]中的元素为null,那么可以放入其中,如果不为空,那么得遍历单链表,要么更新value,要么形成一个新的Entry“挤压”单链表!

hash函数

5b702abd16b2c97380c903e16862e7b27a795ca9

MyHashMap提供的hash函数

050cd3f13a8cb259d4a07c63bfd5136939c3d616

DK的HashMap提供的hash函数

我这里参考了JDK的HashMap的hash函数的实现,这里也再次说明了:要想散列均匀,就得进行二进制的位运算!

resize和rehash

0a51b8ecae52893439a8acd50c9384c6c3454e42

resize/rehash

这里可以看出,对于HashMap而言,如果频繁进行resize/rehash操作,是会影响性能的。

resize/rehash的过程,就是数组变大,原来数组中的entry元素一个个的put到新数组的过程,需要注意的是一些状态变量的改变。

get实现

06726a1ae41900026be30a970dbcc6ad2a63a367

get

get很简单,只需要注意在遍历单链表的过程中使用== or equals来判断下即可。

Test测试

b1af512e9f14138f699c364723144e4fc8f65e8d

利用MyHashMap进行存取

运行结果

972a2bfec24dab953f41f23d8be5a2ce5dd06178

result

OK,一个迷你版的HashMap就写好了,你学到了么?


原文发布时间为:2018-09-6
本文作者:张丰哲
本文来自云栖社区合作伙伴“ java进阶架构师”,了解相关信息可以关注“ java进阶架构师”。
相关文章
|
3月前
|
Serverless
手写一个简单的HashMap
手写一个简单的HashMap
25 0
|
5月前
|
索引
源码分析系列教程(11) - 手写Map框架(基于LinkedList)
源码分析系列教程(11) - 手写Map框架(基于LinkedList)
15 0
HashMap中putMapEntries()方法源码详解
HashMap中putMapEntries()方法源码详解
|
4月前
|
索引
06 # 手写 map 方法
06 # 手写 map 方法
21 0
|
6月前
|
存储 算法 Java
java集合框架Map之HashMap底层原理解析
阈值(threshold) = 负载因子(loadFactor) x 容量(capacity) , 当HashMap中的table数组(桶)的长度 >= 阈值的时候就会自动触发扩容机制
45 0
|
8月前
|
存储 安全 算法
HashMap深入底层原理解析
这次主要是分析下HashMap的工作原理,为什么我会拿这个东西出来分析,原因很简单,以前我面试的时候,偶尔问起HashMap,99%的程序员都知道HashMap,基本都会用Hashmap,这其中不仅仅包括刚毕业的大学生,也包括已经工作5年,甚至是10年的程序员。HashMap涉及的知识远远不止put和get那么简单。本次的分析希望对于面试的人起码对于面试官的问题有所应付
|
9月前
|
存储 Java 开发者
|
10月前
|
网络协议 Java 数据库连接
HashMap源码手写简易篇(数组+链表)
HashMap源码手写简易篇(数组+链表)
|
11月前
|
存储 Java Serverless
HashMap底层原理
1. 基本概念 2. HashMap 的底层数据结构 3. HashMap 的 put 方法流程 4. 怎么计算节点存储的下标 5. Hash 冲突 1)概念 2)解决 hash 冲突的办法 开放地址法 再哈希法 链地址法 建立公共溢出区 6. HashMap 的扩容机制 1)扩容时涉及到的几个属性 2)扩容的条件 3)扩容的简要流程
62 0
|
安全 Java
HashMap源码学习
线程上:HashMap是线程不安全的,而HashTable是安全的。key、value的支持:HashMap的key、balue可以为空,而HashTable是key、value不可以为空的。底层数据结构:HashMap采用数组+链表+红黑树,当链表的长度>=8的时候会考虑是否转成红黑树,而HashTable则没有。初始化容量上:HashTable的初始化容量是11,同时扩容变为原来的2n+1,HashMap的初始化容量是16,同时扩容扩容成原来的2倍。而当给定初始化容量时,HashTable是直接给定初始化容量,而HashMap是将给定的初始化容量变成2的次幂。
51 0
HashMap源码学习

热门文章

最新文章