HashMap解决冲突(简单)

之前也写过这篇文,见Java 8中HashMap和LinkedHashMap如何解决冲突
在java8之前,HashMap等其他基于Map类都是用链地址法解决冲突,它们使用单向链表来存储相同索引值的元素,最坏的情况下,这种方法会使得HashMap的get方法的性能从O(1)降低到O(n)。
为了提高性能,java8中使用平衡树来替代链表存储冲突的元素,那么最坏的性能从O(n)提高到O(logn)。
目前,只有HashMap、LinkedHashMap和ConcurrentHashMap会在频繁冲突的情况下使用平衡树。

在java8中使用常量TREEIFY_THRESHOLD来控制是否切换到平衡树来存储,一般为8,当超过8个元素的索引一样时,hashMap会使用树来存储他们。

java7中的为了优化常用类,对ArrayLIst和HashMap采用了延迟加载的机制,在元素加入之前并不会分配内存,这会减少空的链表和HashMap占用的内存。

这一动态的特性使得HashMap一开始使用链表,并在冲突的元素数量超过指定值时用平衡二叉树替换链表。**不过这一特性在所有基于hash table的类中并没有,**例如Hashtable和WeakHashMap。

什么时候会产生冲突

HashMap中调用HashCode()方法来计算hashcode时。java中的两个不同的对象可能有一样的HashCode,所以不同的键可能有一样的hashcode,从而导致冲突的产生。

总结

  1. HashMap在处理冲突时使用链表存储相同索引的元素。从Java 8开始,HashMap,ConcurrentHashMap和LinkedHashMap在处理频繁冲突时将使用平衡树来代替链表,当同一hash桶中的元素数量超过特定的值便会由链表切换到平衡树,这会将get()方法的性能从O(n)提高到O(logn)。
  2. 当从链表切换到平衡树时,HashMap迭代的顺序将会改变。不过这并不会造成什么问题,因为HashMap并没有对迭代的顺序提供任何保证。
  3. HashTable类从java1就开始存在,是为了保证迭代顺序不变(HashMap的顺序会变),即便在频繁冲突的情况下也不会使用平衡树。这一决定是为了不破坏某些较老的需要依赖于Hashtable迭代顺序的Java应用。
  4. 除了Hashtable之外,WeakHashMap和IdentityHashMap也不会在频繁冲突的情况下使用平衡树。
  5. 使用HashMap之所以会产生冲突是因为使用了键对象的hashCode()方法,而equals()和hashCode()方法不保证不同对象的hashCode是不同的。需要记住的是,相同对象的hashCode一定是相同的,但相同的hashCode不一定是相同的对象。
  6. 在HashTable和HashMap中,冲突的产生是由于不同对象的hashCode()方法返回了一样的值。

以上就是Java中HashMap如何处理冲突。这种方法被称为链地址法,因为使用链表存储同一桶(Bucket)内的元素。通常情况HashMap,HashSet,LinkedHashSet,LinkedHashMap,ConcurrentHashMap,HashTable,IdentityHashMap和WeakHashMap均采用这种方法处理冲突。

从JDK 8开始,HashMap,LinkedHashMap和ConcurrentHashMap为了提升性能,在频繁冲突的时候使用平衡树来替代链表。因为**HashSet内部使用了HashMap,LinkedHashSet内部使用了LinkedHashMap,**所以他们的性能也会得到提升。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值