HashMap重点理解

原理

HashMap基于Hash算法,我们通过put(key,value)存储,get(key)来获取。当传入key时,HashMap会根据key.hashCode()计算出hash值,根据hash值将value保存在bucket里。当数据多的时候肯定会有计算出来的hash值是相同的,这时候发生hash冲突。当数据过多的时候也会自动扩容。


hash冲突

  • jdk1.8之前:数组加链表,hash冲突它会将相同hash值的value追加到链表后面,然后去遍历它。

  • jdk1.8之后:数组加链表加红黑树,引入了一个阈值,那么当大于默认阈值8的时候,它就会将链表变成一个红黑树。


自动扩容

如果在初始化HashMap中没有指定初始容量,那么默认容量为16,负载因子是0.75,如果后来HashMap中存放的数量超过了16×0.75=12的时候,HashMap便会调用resize()方法,扩大为原来的2倍(2的n次幂)。


线程不安全

扩容引发的线程不安全:

  • jdk1.8之前,它会调用到transfer()方法,采用头插法的形式,头插法会将链表的顺序翻转,会形成死循环以及数据丢失的问题。

  • jdk1.8之后,就没有transfer()方法了,采用了尾插法的形式,在并发执行put操作时会发生数据覆盖的情况。


如何保证线程安全

首用CurrentHashMap,也可以用HashTable、加锁、Collections.synchronizedMap(),视情况而定。


为什么用 CurrentHashMap 而不用 HashTable

在迭代的过程中,HashTable加了一个对象锁,会锁定整个map,在多线程环境中效率很低,而ConcurrentHashMap使用分段锁,降低了锁粒度,让并发度大大提高。ConcurrentHashMap将hash表分为16个桶(默认值),诸如get,put,remove等常用操作只锁当前需要用到的桶。试想,原来只能一个线程进入,现在却能同时16个写线程进入并发性的提升是显而易见。


fail-fast

“快速失败”也就是fail-fast,它是Java集合的一种错误检测机制。当多个线程对集合进行结构上的改变的操作时,有可能会产生fail-fast机制。记住是有可能,而不是一定。例如:假设存在两个线程(线程1、线程2),线程1通过Iterator在遍历集合A中的元素,在某个时候线程2修改了集合A的结构(是结构上面的修改,而不是简单的修改集合元素的内容),那么这个时候程序就会抛出ConcurrentModificationException 异常,从而产生fail-fast机制。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值