前言
谈起HashMap我们就不得不提及哈希表了,哈希(Hash)实际上是个人名,由于他提出哈希算法的概念,所以就以他的名字命名了。哈希表(hash table)也叫做散列表,是一种非常高效,复杂度为O(1)的数据结构,我们日常工作中常见的数据结构(数组。线性链表,二叉树,哈希表)等,哈希表不考虑哈希冲突的情况下,处理数据在哈希表中进行添加,删除,查找等操作效率是非常高的,应用场景非常丰富,很多缓存技术(比如memcached)的核心其实就是在内存中维护一张大的哈希表。
一. 什么是哈希表
我们都知道,数据结构的物理存储结构只有两种:顺序存储结构和链式存储结构,在数组中根据下标查找某个元素,一次定位就可以达到,哈希表正是利用了这个特性:哈希表的主干就是数组。
比如我们要新增或者查找某个元素,我们把当前元素的关键字,通过某个函数映射到数组中的某个位置,通过数组下标一次定位就可以达到这个操作。
存储位置 = f(关键字)
其中,这个函数f一般称为哈希函数,这个函数的设计好坏会直接影响到哈希表的优劣,举个栗子,比如我们要在哈希表中执行插入操作:
查找也是同理,先通过哈希算法算出该元素的实际存储地址,然后通过该地址去数组中取出来就可以了。
哈希冲突
假设两个不同的元素,通过哈希算法计算出来的存储地址相同怎么办?也就是说,我们对某个元素进行哈希运算,得到一个存储地址,然后要做插入操作的时候,发现该地址已经被其他元素占用了,这就是所谓的哈希冲突,也叫做哈希冲撞。所以说,好的哈希函数会尽可能的保证计算简单和散列地址分布均匀。但事实上,数组是一块连续的固定长度的内存空间,再好的哈希函数也不能保证得到的存储地址绝对不发生冲突,那么哈希冲突是如何解决的呢?哈希冲突的解决方案有很多种:开放定址法(发生冲突,继续寻找下一块未被占用的存储地址),再散列函数法,链地址法,而HashMap就是采用了链地址法。也就是数组+链表的方式。
二. HashMap的实现原理
HashMap的主干是一个Entry数组。Entry是HashMap的基本组成单元,每一个Entry包含一个key - value键值对。