现在的位置: 首页 > 综合 > 正文

Java 8 中HashMap的改进

2017年12月22日 ⁄ 综合 ⁄ 共 693字 ⁄ 字号 评论关闭

HashMap的快速高效,使其使用非常广泛。其原理是,调用hashCode()和equals()方法,并对hashcode进行一定的哈希运算得到相应value的位置信息,将其分到不同的桶里。桶的数量一般会比所承载的实际键值对多。当通过key进行查找的时候,往往能够在常数时间内找到该value。

但是,当某种针对key的hashcode的哈希运算得到的位置信息重复了之后,就发生了哈希碰撞。这会对HashMap的性能产生灾难性的影响。

在Java 8 之前, 如果发生碰撞往往是将该value直接链接到该位置的其他所有value的末尾,即相互碰撞的所有value形成一个链表。

因此,在最坏情况下,HashMap的查找时间复杂度将退化到O(n).

但是在Java 8 中,该碰撞后的处理进行了改进。当一个位置所在的冲突过多时,存储的value将形成一个排序二叉树,排序依据为key的hashcode。

则,在最坏情况下,HashMap的查找时间复杂度将从O(1)退化到O(logn)。

虽然是一个小小的改进,但意义重大:

1、O(n)到O(logn)的时间开销。

2、如果恶意程序知道我们用的是Hash算法,则在纯链表情况下,它能够发送大量请求导致哈希碰撞,然后不停访问这些key导致HashMap忙于进行线性查找,

最终陷入瘫痪,即形成了拒绝服务攻击(DoS)。但是使用后者之后,能够有效的防止此类攻击,对该攻击所产生的影响会减弱,同时也让HashMap性能的可预测性

有了增强。

注意:

既然有了排序树,则key一定需要排序,那么Key类就需要有Comparable接口进行辅助排序。这是早期版本中key所不具有的。

抱歉!评论已关闭.