在Java 8 以前,HashMap和其余基于map的类都是经过链地址法解决冲突,它们使用单向链表来存储相同索引值的元素。在最坏的状况下,这种方式会将HashMap的get方法的性能从O(1)下降到O(n)。为了解决在频繁冲突时hashmap性能下降的问题,Java 8中使用平衡树来替代链表存储冲突的元素。这意味着咱们能够将最坏状况下的性能从O(n)提升到O(logn)。
在Java 8中使用常量TREEIFY_THRESHOLD来控制是否切换到平衡树来存储。目前,这个常量值是8,这意味着当有超过8个元素的索引同样时,HashMap会使用树来存储它们。
这一改变是为了继续优化经常使用类。你们可能还记得在Java 7中为了优化经常使用类对ArrayList和HashMap采用了延迟加载的机制,在有元素加入以前不会分配内存,这会减小空的链表和HashMap占用的内存。
这一动态的特性使得HashMap一开始使用链表,并在冲突的元素数量超过指定值时用平衡二叉树替换链表。不过这一特性在全部基于hash table的类中并无,例如Hashtable和WeakHashMap。
目前,只有ConcurrentHashMap,LinkedHashMap和HashMap会在频繁冲突的状况下使用平衡树。算法
何时会产生冲突
HashMap中调用hashCode()方法来计算hashCode。
因为在Java中两个不一样的对象可能有同样的hashCode,因此不一样的键可能有同样hashCode,从而致使冲突的产生。性能
总结
HashMap在处理冲突时使用链表存储相同索引的元素。
从Java 8开始,HashMap,ConcurrentHashMap和LinkedHashMap在处理频繁冲突时将使用平衡树来代替链表,当同一hash桶中的元素数量超过特定的值便会由链表切换到平衡树,这会将get()方法的性能从O(n)提升到O(logn)。
当从链表切换到平衡树时,HashMap迭代的顺序将会改变。不过这并不会形成什么问题,由于HashMap并无对迭代的顺序提供任何保证。
从Java 1中就存在的Hashtable类为了保证迭代顺序不变,即使在频繁冲突的状况下也不会使用平衡树。这一决定是为了避免破坏某些较老的须要依赖于Hashtable迭代顺序的Java应用。
除了Hashtable以外,WeakHashMap和IdentityHashMap也不会在频繁冲突的状况下使用平衡树。
使用HashMap之因此会产生冲突是由于使用了键对象的hashCode()方法,而equals()和hashCode()方法不保证不一样对象的hashCode是不一样的。须要记住的是,相同对象的hashCode必定是相同的,但相同的hashCode不必定是相同的对象。
在HashTable和HashMap中,冲突的产生是因为不一样对象的hashCode()方法返回了同样的值。
以上就是Java中HashMap如何处理冲突。这种方法被称为链地址法,由于使用链表存储同一桶内的元素。一般状况HashMap,HashSet,LinkedHashSet,LinkedHashMap,ConcurrentHashMap,HashTable,IdentityHashMap和WeakHashMap均采用这种方法处理冲突。优化
从JDK 8开始,HashMap,LinkedHashMap和ConcurrentHashMap为了提高性能,在频繁冲突的时候使用平衡树来替代链表。由于HashSet内部使用了HashMap,LinkedHashSet内部使用了LinkedHashMap,因此他们的性能也会获得提高。.net
HashMap的快速高效,使其使用很是普遍。其原理是,调用hashCode()和equals()方法,并对hashcode进行必定的哈希运算获得相应value的位置信息,将其分到不一样的桶里。桶的数量通常会比所承载的实际键值对多。当经过key进行查找的时候,每每可以在常数时间内找到该value。code
可是,当某种针对key的hashcode的哈希运算获得的位置信息重复了以后,就发生了哈希碰撞。这会对HashMap的性能产生灾难性的影响。对象
在Java 8 以前, 若是发生碰撞每每是将该value直接连接到该位置的其余全部value的末尾,即相互碰撞的全部value造成一个链表。blog
所以,在最坏状况下,HashMap的查找时间复杂度将退化到O(n).排序
可是在Java 8 中,该碰撞后的处理进行了改进。当一个位置所在的冲突过多时,存储的value将造成一个排序二叉树,排序依据为key的hashcode。索引
则,在最坏状况下,HashMap的查找时间复杂度将从O(1)退化到O(logn)。内存
虽然是一个小小的改进,但意义重大:
一、O(n)到O(logn)的时间开销。
二、若是恶意程序知道咱们用的是Hash算法,则在纯链表状况下,它可以发送大量请求致使哈希碰撞,而后不停访问这些key致使HashMap忙于进行线性查找,最终陷入瘫痪,即造成了拒绝服务攻击(DoS)。————————————————版权声明:本文为CSDN博主「buder得儿得儿以得儿以得儿得儿」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处连接及本声明。原文连接:https://blog.csdn.net/cpcpcp123/article/details/52744331