HashMap实现原理概述
博客专区 > 6pker 的博客 > 博客详情
HashMap实现原理概述
6pker 发表于2年前
HashMap实现原理概述
  • 发表于 2年前
  • 阅读 128
  • 收藏 17
  • 点赞 2
  • 评论 0

腾讯云 技术升级10大核心产品年终让利>>>   

1. HashMap的数据结构

数据结构中有数组链表来实现对数据的存储,但这两者基本上是两个极端。


数组

数组存储区间是连续的,占用内存严重,故空间复杂的很大。

但数组的二分查找时间复杂度小,为O(1);

数组的特点是:寻址容易,插入和删除困难


链表

链表存储区间离散,占用内存比较宽松,故空间复杂度很小。

但时间复杂度很大,达O(N)。

链表的特点是寻址困难,插入和删除容易。


哈希表

哈希表((Hash table)既满足了数据的查找方便,同时不占用太多的内容空间,使用也十分方便。

哈希表有多种不同的实现方法,我接下来解释的是最常用的一种方法—— 拉链法,我们可以理解为“链表的数组” ,如图:



从上图我们可以发现哈希表是由数组+链表组成的,一个长度为16的数组中,每个元素存储的是一个链表的头结点。

那么这 些元素是按照什么样的规则存储到数组中呢。

一般情况是通过hash(key)%len获得,也就是元素的key的哈希值对数组长度取模得到。

比如上述哈希 表中,12%16=12,28%16=12,108%16=12,140%16=12。所以12、28、108以及140都存储在数组下标为12的位置。


HashMap其实也是一个线性的数组实现的,所以可以理解为其存储数据的容器就是一个线性数组。

首先HashMap里面实现一个静态内部类Entry,其重要的属性有key , value, next

从属性key,value我们就能很明显的看出来Entry就是HashMap键值对实现的一个基础bean,我们上面说到HashMap的基础就是一个线性数组,这个数组就是Entry[],Map里面的内容都保存在Entry[]里面。


2. HashMap的存取实现

  既然是线性数组,为什么能随机存取?这里HashMap用了一个小算法,大致是这样实现:

// 存储时:
int hash = key.hashCode(); // 这个hashCode方法这里不详述,只要理解每个key的hash是一个固定的int值
int index = hash % Entry[].length;
Entry[index] = value;

// 取值时:
int hash = key.hashCode();
int index = hash % Entry[].length;
return Entry[index];


这里HashMap里面用到链式数据结构的一个概念。

上面我们提到过Entry类里面有一个next属性,作用是指向下一个Entry。

打个比方, 第一个键值对A进来,通过计算其key的hash得到的index=0,记做: Entry[0] = A

一会后又进来一个键值对B,通过计算其index也等于0,现在怎么办?

HashMap会这样做: B.next = A, Entry[0] = B,

如果又进来C, index也等于0, 那么 C.next = B, Entry[0] = C

这样我们发现index=0的地方其实存取了A,B,C三个键值对, 他们通过next这个属性链接在一起。

所以疑问不用担心。也就是说数组中存储的是最后插入的元素到这里为止,HashMap的大致实现,我们应该已经清楚了。



标签: Java
共有 人打赏支持
粉丝 49
博文 97
码字总数 59339
×
6pker
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: