茶杯熟了

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 :: 管理 ::

jdk1.8 HashMap put与get方法分析

不言而喻,现在很多面试的时候,尤其是大厂,总是不经意的问一下java底层的东西,他们更关注的是你的基础。
今天就读一下hashmap的源码,简单分析一下(面试被搞得头疼,回来会就先粗略地看了一番)。
HashMap,顾名思义就是跟hash有关:
下面是hashmap中的hash方法,首先传入map的key值,根据这个key的hashcode值算出一个hash值。这个hash值后面会用得到。
首先我们看下hashmap的存储结构:
    hashmap底层是由数组+链表结构(链表负责存储数据,实现了内部的Entry<K,V>接口)
如图:
        
面试中常用到的也就是map的put和get方法。
首先我们看下put方法:
    
put方法调用了putVal方法,传入了key的hash值,key和value。
一步步分析:
  • 当我们第一次初始化map,调用put方法:
        
        首先简单介绍下tab和p的区别,tab就是当前链表,p就是当前链表的i个值,n为链表的长度,i为index索引。
         标红判断,当前链表是否为null,如果为空就初始化resize方法,后期当map长度超过了阀值(0.75)时,进行第二个扩容,扩容大小为*2
  • 进行存储:
        
        至于存储的位置判断:新put的数据应该存储到哪个位置呢?
  1. 标红处,使用key的hash值和数组长度进行与运算得到下表i,判断这个下面的是否存在值,如果不存在,就在该下面i下初始化一个链表        
        
  • 当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方法:
    
    • 调用getNode方法,也是get方法的核心方法。
    
    1. 首先判断table是否为空,并且hash值算出当前索引下node是否为空。
      1. 如果第一个节点hash值相等,key也相当,那就是第一个值,直接返回
      2. 如果第一个节点不相等
        1. 判断是否为红黑树类型,如果是从树种获取数据
        2. 不是红黑树类型,进行while遍历下一个节点,知道节点的hash值,key值相等,返回。
    2. 为空直接返回null
简简单单看了一下,差不多就是这个样子吧。
 
        
 
 
 
posted on 2019-01-05 13:32  茶杯熟了  阅读(873)  评论(0)    收藏  举报