目录
二:HashMap的工作原理【put()/get()方法工作原理】
三:在多线程的情况重新调整HashMap大小存在什么问题吗?
四:HashMap是非线程安全【非synchronized】
转发文章地址:https://blog.csdn.net/qq_38200425/article/details/114281175
一:HashMap的特性
1、HashMap实现了Map接口,存储键值对。
2、HashMap允许键和值为null【不允许重复的键】,而Hashtable则不能。
3、HashMap是非线程安全【非synchronized】
4、HashMap的增删操作是在链表上完成的,而查询只需扫描部分,则效率高。
HashMap是哈希表结构,有数组结构和链表结构的优点。
二:HashMap的工作原理【put()/get()方法工作原理】
1、hashmap实现原理
HashMap是基于hashing的原理,我们使用put(key, value)存储对象到HashMap中,使用get(key)从HashMap中获取对象。
当我们给put()方法传递键和值时,我们先对键调用hashCode()方法,返回的hashCode用于找到bucket位置来储存Entry对象。
2、map.put(key,value)实现原理
(1)首先将k,v封装到Node对象当中(节点)。
(2)然后它的底层会调用K的hashCode()方法得出hash值。
(3)通过哈希表函数/哈希算法,将hash值转换成数组的下标,下标位置上如果没有任何元素,就把Node添加到这个位置上。如果说下标对应的位置上有链表。此时,就会拿着k和链表上每个节点的k进行equal。如果所有的equals方法返回都是false,那么这个新的节点将被添加到链表的末尾。如其中有一个equals返回了true,那么这个节点的value将会被覆盖。
3、map.get(key)实现原理
(1)先调用k的hashCode()方法得出哈希值,并通过哈希算法转换成数组的下标。
(2)通过上一步哈希算法转换成数组的下标之后,在通过数组下标快速定位到某个位置上。如果这个位置上什么都没有,则返回null。如果这个位置上有单向链表,那么它就会拿着K和单向链表上的每一个节点的K进行equals,如果所有equals方法都返回false,则get方法返回null。如果其中一个节点的K和参数K进行equals返回true,那么此时该节点的value就是我们要找的value了,get方法最终返回这个要找的value。
三:在多线程的情况重新调整HashMap大小存在什么问题吗?
https://blog.csdn.net/suifeng629/article/details/82179996
存在两个问题,一是数据丢失。二是重排可能会引起链表打结锁死,下下次get的时候陷入死循环的equals。jdk1.8已经对hashmap进了优化。
resize排序规则的改变红黑树避免了死循环和最坏的碰撞性能问题。但是数据丢失问题仍然不能避免。所以多线程下不要使用hashMap。可能hashMap多线程还有我们未知的安全问题。
四:HashMap是非线程安全【非synchronized】
HashMap是非synchronized的,但collection框架提供方法能保证HashMap 线程安全(synchronized),这样多个线程同时访问HashMap时,能保证只有一个线程更改Map。
在多线程下为什么还要用hashmap呢?用hashtable不行吗?