HashMap底层分析总结

一、HashMap常见问题?
对比HashTable是线程不安全的,效率高,允许null值存取,键值对存储。

二、HashMap执行put()方法时做了哪些操作?
HashMap是基于hashing的原理,使用put(key,value)存储对象到hashMap中,使用get(key)获取存储
的对象。使用put()传递键值对的时候,先对key调用hashCode(),返回hashCode用于找到bucket位置来存储Entry对象。
:关键在于HashMap是在bucket中存储键对象和值对象的。

3、当两个对象的hashCode相同是会发生什么?
首先要明白,就算两个对象的hashCode相同并不代表这两个对象相等。因为hashCode相同,所以她们的bucket位置相同,“碰撞”会发生。因为HashMap是用链表存储对象,这个Entry(包含有键值对的Map.Entry对象)会存储在链表中

4、如果两个键对象的hashCode相同,如何获取值对象?
当调用get()方法时,HashMap会使用键对象的hashCode找到bucket位置,然后调用keys.equals()找到链表的正确的节点,最终找到要找的值对象。

5、如何减少碰撞?
使用不可变的、声明为final的对象做键值,并采用合适的equals()和hashCode()方法能减少碰撞发生,提高效率。

6、如何HashMap的大小超过了负载因子(load factor)定义的容量,怎么办?
默认的负载因子大小是0.75,也就是说当一个map填满了75%的bucket的时候,它就会跟其他集合对象一样比如ArrayList,创建HashMap原来大小的两倍bucket数组来重新调整map的大小,并将原来的对象放入心得bucket数组中。这个过程叫做rehashing,因为它调用hash方法找到心得bucket位置。

7、你了解重新调整HashMap大小存在什么问题吗?
在多线程的情况下会存在条件竞争的问题。
当多个线程都发现HashMap需要调整大小的时候,它们会同时试着调整大小。在调整大小的过程中,链表中的次序是反过的,因为在移动到新的bucket位置的时候,HashMap不会将元素存在链表的尾部,而是放在头部,为了避免尾部遍历。如果条件竞争发生了,那么就死循环了。


猜你喜欢

转载自blog.csdn.net/qq_26629277/article/details/80505155