HashMap

哈希表

要理解HashMap,首先得知道什么是哈希表
哈希表是用来存储数据的一种数据结构,其表现形式如下哈希表
哈希表的主干是数组,如果我们需要存储某个元素,那么我们需要通过一个哈希函数确定此元素在哈希表(数组)中的位置,再将此元素存进去

也就是说哈希表的存储过程如下

x → f(hash) → 地址 → 存放

那么这就难免出现通过哈希函数f所求到的地址一样的情况,这种情况称为哈希冲突,或者哈希碰撞。
这个时候就有人提出了这样的办法,在数组的某个位置尾端加一个链表来解决哈希冲突,例如这样子:哈希表
当x和y通过哈希函数f都求出了同一个地址,那么后来的y将存放在此地址下的链表中
这种方法称为链地址法,而HashMap正是运用了这种存储结构

HashMap

HashMap继承于AbstractMap类,实现了Map接口。Map是"key-value键值对"接口,AbstractMap实现了"键值对"的通用函数接口。

HashMap是通过"拉链法"实现的哈希表。它包括几个重要的成员变量:table, size, threshold, loadFactor, modCount。

table是一个Entry[]数组类型,而Entry实际上就是一个单向链表。哈希表的"key-value键值对"都是存储在Entry数组中的。

size是HashMap的大小,它是HashMap保存的键值对的数量。

threshold是HashMap的阈值,用于判断是否需要调整HashMap的容量。threshold的值=“容量*加载因子”,当HashMap中存储数据的数量达到threshold时,就需要将HashMap的容量加倍。

loadFactor就是加载因子。

modCount是用来实现fail-fast机制的(快速失败机制,一种错误检测机制,当多个线程对集合进行结构上的改变操作时,就有可能会产生fail-fast事件)。

HashMap的实现原理

HashMap的主干是数组+链表,要注意的是它存储的是键值对,而除了键值对外还存有hash值以及指向下一个地址的指针next,它的整体结构如下:
在这里插入图片描述
HashMap的存储过程

  • x → f(hash) → 地址 → 是否冲突?
    否:直接存放
    是:存放到链表中

HashMap的查找过程

  • x → f(hash) → 地址 → 是否为所需值?
    是:找到返回结果
    否:遍历链表,用key对象的equals方法判断是否为所需值

当发生哈希冲突并且size大于阈值的时候,要对哈希表进行扩容,将原大小的数组扩展为原来的2倍新数组,并且将原来Entry数组中的东西全部传输到新的数组中。

同时我们应该知道:

  • HashMap的数组大小一定是2的n次幂,这样能使哈希冲突的概率更小
  • 如果我们重写了equals方法,那么对应地要重写hashCode方法
  • HashMap是线程不安全的

为什么HashMap的数组大小(负载因子)一定是2的 n次幂

一个哈希表为了减少哈希运算,我们可以运用取余的办法,也就是说当往一个数组大小为16的HashMap中填充数据的时候,我们利用%确定这个数据对象的位置,例如我要把11放进这个hashmap,那么我们通过11%16等于11的方法,判断到11这个数应该放在第十一个桶。

但是在计算机中,取余的计算效率是不高的,然后工程师就想到了按位与&的方法,怎样才能利用&达到和取余相同的功能呢?这就是这个问题的关键。我们可以发现,只要实现按位与的另一个数二进制全为1就能够实现相同的功能。例如,11的二进制01011,与01111按位与的话,得到的是01011,还是11,效果一样。

那么为什么是2的n次幂?我们可以想想2的n次幂用二进制都是怎样表示的。 2 4 2^{4} 24=16的二进制是10000, 2 3 2^{3} 23=8的二进制是1000,发现了吗,2的几次方就是1后面跟多少个0,顺着这个思路想,只要 2 n 2^{n} 2n-1就是0111…1111的形式,是不是就可以实现这个功能了呢?

所以只要实现了length为 2 n 2^{n} 2n,那么hash%length==hash&(length-1)就能够成立了

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值