JDK1.8源码之HashMap

Posted youtang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDK1.8源码之HashMap相关的知识,希望对你有一定的参考价值。

一.哈希表

  本文首先介绍一下哈希表,因为要解析HashMap,理解其内部结构以及原理,不得不提到哈希表。

  哈希表是根据关键值key直接进行数据访问的数据结构,其本质是一个数组,数组的每一个元素为一个“桶”,桶中存放键值对。其存储过程是根据每个数据通过哈希函数计算的哈希值决定其存放的桶的下标。若桶中存在键值对,则使用寻址法或链地址法解决冲突。

  这里提到的哈希函数,也称为散列函数,具有以下几个特点:

  • 输入域无限大,输出域有限大。即给定任意长度的输入,通过算法,得到等长的输出。
  • 不包含任何随机的东西,输入相同时输出一定相同。
  • 不同的输入可能导致相同的输出(称为哈希碰撞,概率极低)。
  • 大量的输入出现时,对于输出域中每个点的厚度而言是均匀变厚的(厚度:重复率),体现了哈希函数最重要的性质:均匀性

  经常使用的MD5算法就是一种哈希函数。

  在哈希表中,数据的key值通过hash函数得到hash值,hash值mod哈希表的长度(即桶的个数)得到的值就存放的桶的下标,范围为0~桶的个数-1,在HashMap中,使用链地址法解决冲突,所以,桶中存放的就是键值对的链表。

  在哈希表中还有一个重要的概念——负载因子,主要是衡量哈希表的空满程度。

  负载因子=总的键值对的个数/桶的个数

  负载因子越大,代表哈希表越满,每个桶中的链表越长,更容易导致冲突,性能越差,此时哈希表将自动扩容。

  哈希表每次扩容,一般将桶的个数增加至之前的两倍,由于桶的数量增加,则需重新计算所有数据的哈希值,mod新的哈希表的长度,得到新的桶的地址,重新挂链,由此可见,扩容的代价是全量的,但是,扩容后的哈希表的每个桶的链的长度基本是之前的一半,所以说扩容后,很久都不需要扩容(除非有极端情况,数据的key计算出的哈希值都一样,扩容后位置不变),同时在java8的HashMap中,引入了红黑树,使HashMap的性能更高。

二.HashMap

  未完待续>_<

  

 

  

以上是关于JDK1.8源码之HashMap的主要内容,如果未能解决你的问题,请参考以下文章

JDK1.8源码之HashMap(上)

JDK1.8源码泛读之Arrays

JDK1.8源码分析之HashMap

JDK1.8源码分析之TreeMap

JDK1.8源码分析之LinkedHashMap

JDK1.8 源码分析之HashMap