hashmap的实现原理

转载自一位大佬的博客:https://blog.csdn.net/qq_40118851/article/details/82804510 【hashmap的底层实现原理】图文+源码。写的很棒。

 

我的一些理解:

要想知道hashmap的优点,需要知道时间复杂度的概念。hashmap实现了插入、删除、查找的时间复杂度都为O(1),这代表他的执行效率极高。

一:为什么哈希表的插入、删除、查找操作的时间复杂度都为O(1)

数组在已知下标的情况下,查找的时间复杂度为O(1)。哈希表正是利用了这一特征,哈希表的主干就是数组(有人称为“桶”结构)。

【  储存位置 = f(关键字)】这个函数称为哈希函数 是一个重要的概念,这个函数的设计好坏直接影响到哈希表的优劣。例如:完成插入操作——利用哈希函数通过关键字计算出实际储存位置,然后映射到数组的某一个位置。

删除、查找类似插入操作。

**问:为什么一般数组的插入时间复杂度为O(n),而哈希表的插入为O(1)?

答:【与一般数组的插入不同!哈希表用到的数组是有默认预设大小(为16)的,原则是足够用的同时尽可能地小(提高效率),不够用时可以进行扩充(原理很重要)。所以是“映射”到数组的某一个位置,他不会导致数组其他元素位置的变化(这也是为什么一般数组的插入除在末尾插入的时间复杂度为O(1)外,在其他位置插入都为O(n)),所以哈希表插入的时间复杂度为O(1)】

哈希冲突

因为储存位置是通过哈希函数计算出来的,所以不能避免的会出现两个不同的元素计算出的储存位置相同,此时就发生了哈希冲突(也叫哈希碰撞)。所以前面说一个好的哈希函数设计至关重要,要尽可能的保证计算简单和散列地址分布均匀。但是再好的哈希函数也不能保证冲突不会发生,这是就需要其他的解决办法,如:开放地址法(发生冲突后,继续寻找下一块未被占用的储存地址),再散列函数法,链地址法。而HashMap就采用了链地址法,也就是数组+链表的方式(详情见上方大佬博客).

HashMap由数组+链表组成的,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的,如果定位到的数组位置不含链表(当前entry的next指向null),那么对于查找,添加等操作很快,仅需一次寻址即可;如果定位到的数组包含链表,对于添加操作,其时间复杂度为O(n),首先遍历链表,存在即覆盖,否则新增;对于查找操作来讲,仍需遍历链表,然后通过key对象的equals方法逐一比对查找。所以,性能考虑,HashMap中的链表出现越少,性能才会越好。也就是说在出现哈希冲突时,由于单链表的出现,HashMap的查找、添加等操作的时间复杂度就不再全是O(1)了。因为需要遍历单链表,所以时间复杂度会是O(n)。

**写在最后:一定要细看并理解源码,非常重要,理解之后会非常有成就感!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值