HashMap的一些整理

JAVA面试必备(一) HashMap(基于jdk1.8)@TOC

JAVA面试必备(一) HashMap(基于jdk1.8

概述

HashMap(1.8)底层是由Node类型的数组、链表、红黑树组成的,接下来将会分析其put、resize、get、replace方法

1、 讲一下HashMap的put原理:

Put底层其实调用的是putval()方法,在put时,首先会算出当前Node的下标值
具体算法是,(1)算出key的hashCode值,然后再根据算出的值通过扰动函数再算一遍,扰动函数具体做法是:将算出的hashCode值与其高16位再做一次异或运算,这么做原因是因为:再刚开始时,table的length比较小,如16、32.
这样length的高位都会是0,这样直接通过路由寻址公式(table.length-1)&node.hash显然对key的hashcode的高位不公平,因为算出来都是0,如果添加了扰动函数,更合理,也能让哈希算的更加散列。
以上是找出了index值,接下来是真正的put操作了
根据源码可以得知,分为以下几种情况
(1) 如果当前下标没有值,那么就直接将node存储到hash表中
(2) 如果当前下标有值了,且找到了一个与当前要插入的Node的key一致的key,则需要做一次value覆盖的操作
(3) 如果是红黑树形式:待补充
(4) 如果是链表的形式,会做一次for循环遍历,如果遍历到最后也没找到key相同的情况,则加入到当前链表的末尾,如果找到了相同的key则跳出当前循环,做一次覆盖的操作,当遍历了8次后,则树化
如果添加元素超过了阈值,则需要进行一次扩容操作。

2、讲一下resize原理:

  1. Resize发生再两个阶段:初始化阶段和需要扩容的阶段,都会调用resize()
  2. Resize源码分析:首先会计算出扩容后table的大小和阈值,
  3. 如果之前的table已经初始化过了(oldCap>0),则再正常条件下(大小没有超过MAX_CAPACITY)时,会把容量扩大位原来的2倍,阈值也扩大到原来的2倍
  4. 如果之前的table初始化但是还没赋值,则(oldCap=0),那么会根据初始化时调用的构造方法通过tablesizefor函数来指定其table大小,HashMap构造方法
    //1.new HashMap(initCap,loadFactor);
    //2.new HashMap(initCap);
    //3.new HashMap(map);并且这个map有数据
    // 通过tableSizeFor方法(为阈值人为赋值,即oldThr有值,输入值最大的2的幂次数 9---->16)
    若初始化时调用HashMap() 这个无参数构造的话,则直接赋值为默认值,容量为16,阈值为12
    ----以上只是将table的size和阈值指定出来----
    ----接下来是真正的扩容:-----
    会根据table的长度创建一个更大的数组,
    第一种情况:如果旧表中的桶中只有一个元素,则直接把值放入新桶中,
    第二种情况:桶位是否被树化,待补充
    第三种情况:旧表种是链表的情况,则会生成两个链表:低位链表和高位链表
    低位链表表示(举例子,假设原表长度为16,则15& 01111为低位11111为高位都会放在15的位置上)
    从源码来看,低位链表就是放在之前的位置上(15)了,而高位链表放在了15+oldcap(15+16=31的位置上),插入后滞空,表示再末尾(尾插法)

3、 讲一下get方法:

返回的是getNode方法,需要通过hash算法算出对应的数组下标,如果对应下标没值则返回null,如果有值 三种情况:
(1) 第一种情况:定位出来的桶位元素,就是我们要get的数据,直接返回结果
(2) 当前桶位不止一个元素可能是链表,那么就遍历,找相同的元素,直到找到
(3) 当前桶位是红黑树TODO

4、 讲一下remove方法:

返回的是removeNode方法,其中有一个matchValue参数,matchValue为true则表示只有再key相同value也相同时才删除,remove(key)中的为false
和get类似,先去找有无对应的元素,找到了则赋值给一个临时变量node
如果是链表则做链表删除操作,如果是树 TODO

5、replace方法:两种

  1. replace(key,value):通过getNode方法找到对应的key,将新value覆盖
  2. replace(K key, V oldValue, V newValue):首先通过给getNode找到对应的key,然后判断oldValue是不是原来的value,是的话则将新值覆盖即可
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值