HashMap学习笔记

1.简述

HashMap是Java开发过程中使用最多的集合之一,其中的put(key,value)和get(key)方法,是我们在使用HashMap时最常使用的方法,但是底层的原理我们可能就了解得比较少了,或许你知道HashMap是使用hash算法,然后基于数组+链表+红黑树来实现的,或许还知道HashMap内部数组的初始长度为16,并且还能自动扩容.今天我们就来探究一下put(key,value)和get(key)这两个常用的方法的实现过程和原理.

2. put(key,value)的原理

首先我们调用put方法的时候,方法内部会调用hash(key)方法,计算出key的hash值h,然后通过HashMap的主干部分(数组tab)的长度length来进行位与运算(length-1)&h得出一个index=(length-1)&h值,然后直接根据index的值,将Node对象放入对应的tab[index]=Node即可,如下图所示:
在这里插入图片描述虽然在计算index的时候采用的是均匀分布算法,但是当put的key-value越来越多时,不可避免的会出现计算的index出现重复,这个时候就需要用到链表结构了,其实我们的Node对象不仅仅是数组里面的一个元素,还是可能是一个链表的头节点,通过next指向链表的下一个Node对象节点.当出现重复index的时候则以下面的方式进行插入:
在这里插入图片描述
另外当链表的长度达到一定值(默认为8)之后,会转换成红黑树的结构,如下图
在这里插入图片描述

3.get(key)的原理

一般情况下,首先根据key值调用方法hash(key),通过与数组长度位与运算来计算出index值,然后直接返回tab[index].value即可.
但是当计算出的index处的Node对象是链表结构或红黑树时,应该怎么办呢,因为那里所有Node的index都是相同的.

当是链表结构时,这个时候会使用node.next来依次遍历比较链表上每个Node对象节点的key值是否和传入的key相等,直到匹配上为止.如下伪代码和图所示:
在这里插入图片描述
当是红黑树结构时则node实际就为TreeNode对象,由对象调用getTreeNode方法进行内部匹配,这里对红黑树的内部如何匹配就不做介绍了,感兴趣的朋友可以自行查资料.

4.常见问题

  1. 为什么位运算?
    Hash算法最终得到的index结果,完全取决于Key的Hashcode值的最后几位。
    也就是说,当HashMap长度为10的时候,有些index结果的出现几率会更大,而有些index结果永远不会出现(比如0111)!
    这样,显然不符合Hash算法均匀分布的原则。
    反观长度16或者其他2的幂,Length-1的值是所有二进制位全为1,这种情况下,index的结果等同于HashCode后几位的值。只要输入的HashCode本身分布均匀,Hash算法的结果就是均匀的。

2.为什么尾插
头插法是操作速度最快的,找到数组位置就直接找到插入位置了,但是课程里演示过,
jdk8之前hashmap这种插入方法在并发场景下如果多个线程同时扩容会出现循环列表。
jdk8开始hashmap链表在节点长度达到8之后会变成红黑树,这样一来在数组后节点长
度不断增加时,遍历一次的次数就会少很多很多(否则每次要遍历所有),相比头插法
而言,尾插法操作额外的遍历消耗已经小很多了,也可以避免之前的循环列表问题。
(同时如果变成红黑树,也不可能做头插法了)

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值