HashMap源码初步分析

一、HashMap是什么?

    HashMap 是一个散列(哈希)表,它存储的内容是键值对(key-value)映射。通过put()方法存储对象,get()方法获取对象。

    HashMap 存放的元素是无序的,允许空键和空值(null),但是空键只能有一个,且放在第一位。

    HashMap 的数据结构是由 “数组” + “链表” 来实现对数据的存储。

    (1)数组:占用空间连续,寻址容易,查询速度快,但是增加和删除的效率非常低。

    (2)链表:占用空间不连续,寻址困难,查询速度慢,但是增加和删除的效率非常高。(数组和链表的特点相反)

    HashMap则结合了数组和链表的优点(即查询快,增删效率高)。

    (HashMap是一种非常重要的数据结构,对于我们以后理解很多技术都非常有帮助,

         比如:redis数据库的核心技术和HashMap差不多)

二、HashMap源码分析

注:本文使用jdk1.8分析HashMap源码

    1.HashMap存储数据的过程:

        理解了HashMap的基本结构之后,我们来继续深入学习HashMap如何存储数据。

        首先,我们来查看HashMap的源码,如下图:


P28)102QTZ~CHAX$4SWIS(C

    DEFAULT_INITIAL_CAPACITY: Node数组的默认长度(必须为2的整数幂)。

    DEFAULT_LOAD_FACTOR:当Node数组实际装的数量达到了75%就会自动扩容。

    Node数组:HashMap存放的元素都在Node数组中,每一个Node对象就是一个单向链表结构

              (所以称HashMap的存储结构是“数组”+“链表”)

    Node数组源码如下:

@[$`5WD23VX1CAU3$1O265H

    hash:每当HashMap存入一个元素,先根据key计算出一个hash值,得到一个存放位置。

        存放位置=hash值%(Node数组长度-1)

        那么不同的key计算出的hash值%(Node数组长度-1)会不会有一样的存放位置呢?答案是有。

    next:Node数组中的单向链表,一旦发生冲突(一样的存放位置),那么冲突的元素则被存放在next中,以此类推。


手绘大师

    上面说到,冲突的元素会放在链表(next)中,如果冲突的元素过多,那么查询的效率则会降低(链表的缺点),在jdk1.8中当链表存    储冲突的元素过多时,会采用红黑树来替代链表,从而解决查询效率低的问题。 而链表与红黑树之间的转换则由以下三个静态常量控制:

    下面这段源码依旧是HashMap中的。

TJ9)UG8DVH)B@W}7L9UEL77



总结:

      HashMap内部的数据结构:“数组”+“链表”。

      HashMap存放元素的位置=key的hash值%(Node数组长度-1)。

      HashMap处理冲突的元素是把冲突的元素存放在链表中,当冲突的数量>树化阈值则采用红黑树。

     

     

本文若有错误请留言指正,谢谢

猜你喜欢

转载自www.cnblogs.com/zyonghua/p/12664072.html