jdk1.8 HashMap put与get方法分析

不言而喻,现在很多面试的时候,尤其是大厂,总是不经意的问一下java底层的东西,他们更关注的是你的基础。

今天就读一下hashmap的源码,简单分析一下(面试被搞得头疼,回来会就先粗略地看了一番)。

HashMap,顾名思义就是跟hash有关:

jdk1.8 HashMap put与get方法分析

下面是hashmap中的hash方法,首先传入map的key值,根据这个key的hashcode值算出一个hash值。这个hash值后面会用得到。

首先我们看下hashmap的存储结构:

    hashmap底层是由数组+链表结构(链表负责存储数据,实现了内部的Entry<K,V>接口)

如图:

        jdk1.8 HashMap put与get方法分析

面试中常用到的也就是map的put和get方法。

首先我们看下put方法:

    jdk1.8 HashMap put与get方法分析

put方法调用了putVal方法,传入了key的hash值,key和value。

一步步分析:

  • 当我们第一次初始化map,调用put方法:

        jdk1.8 HashMap put与get方法分析

        首先简单介绍下tab和p的区别,tab就是当前链表,p就是当前链表的i个值,n为链表的长度,i为index索引。

         标红判断,当前链表是否为null,如果为空就初始化resize方法,后期当map长度超过了阀值(0.75)时,进行第二个扩容,扩容大小为*2

  • 进行存储:

        jdk1.8 HashMap put与get方法分析

        至于存储的位置判断:新put的数据应该存储到哪个位置呢?

  1. 标红处,使用key的hash值和数组长度进行与运算得到下表i,判断这个下面的是否存在值,如果不存在,就在该下面i下初始化一个链表        

        jdk1.8 HashMap put与get方法分析

  • 当key的hash值与数组的索引已经有数据存在时:

    1. 判断当前索引的下p的hash与要存储的数据hash是否有冲突(p的key值与存入数据的key是否相等)

      1. 相等>>>将p指向e

    2. 如果hash不冲突,并且p的类型为tree节点类型,使用红黑树往下面树节点进行数据存储。

    3. 如果hash不冲突也不是树节点类型

      1. 判断p节点的next为空,

        1. 新数据添加到p节点后面

        2. 如果链表的长度已经达到了8个(默认链表只能存储8个),则转换为红黑树进行存储。

      2. 如果p节点额next不为空

        1. e节点有hash冲突,直接把p节点使用e节点替换

    4. e节点不为空(经过前面的一系列赋值,e节点已经不为空了)

      1. 将e节点的value替换老V的值

    5. 索引往后移动。

其次我们看下get方法:

    jdk1.8 HashMap put与get方法分析

    jdk1.8 HashMap put与get方法分析

  • 调用getNode方法,也是get方法的核心方法。

    1. 首先判断table是否为空,并且hash值算出当前索引下node是否为空。

      1. 如果第一个节点hash值相等,key也相当,那就是第一个值,直接返回

      2. 如果第一个节点不相等

        1. 判断是否为红黑树类型,如果是从树种获取数据

        2. 不是红黑树类型,进行while遍历下一个节点,知道节点的hash值,key值相等,返回。

    2. 为空直接返回null

简简单单看了一下,差不多就是这个样子吧。希望有所帮助,不对地方请改正