java底层学习-HashMap

HashMap是一种常用的Java数据结构,通过hashcode快速定位元素。当发生碰撞时,它使用单链表解决冲突。影响HashMap性能的因素包括初始容量和加载因子,当元素达到特定阈值时会自动扩容。线程不安全的HashMap在多线程环境下需采取同步措施,如使用ConcurrentHashMap。

hashmap的存取方式

当我们调用put方法时,hashmap会首先会调用hashcode方法获取hash码,通过hash码快速找到某个位置,这个位置被称为bucket index([ˈbʌkɪt],桶),找到这个位置后会有三种情形,第一种,bucketindex位置没有元素:直接将k,v存储;第二种,bucketindex有元素并且对象相同:替换v;第三种,bucket index有元素但对象不同,也将这个元素放到这个位置然后通过一个单链表来维护这种关系。

Get方法同理,都是首先调用hashcode方法获取hash码来快速定位找到k,返回v

Hashmap碰撞

上面讲到调用put方法第三种情况也就是hashmap碰撞问题,大多在大数据量的情况下,或者人为生成唯一性较弱的hashcode情况下;hashcode碰撞简单讲就是两个不同的k计算出了同样的hashcode。hashmap是通过单向链表(Entry)来解决碰撞问题的,当碰撞发生了,对象会存储在链表的下一个节点(Entry<k,v> )中。Hashmap在每个链表节点存储键值对对象,当调用get方法的时候通过bucket位置来获取链表对象,然后通过equals方法来找到v,这个方法就叫做拉链法

hashmap影响性能的因素

构造方法的两个参数:初始容量(initialCapacity)加载因子(loadFactor),默认初始容量是16,加载因子是0.75f,hashmap默认构造可存储16 * 0.75 = 12个元素。

加载因子0.75是在时间成本和空间成本做了折中,过高的加载因子虽减少了空间开销,但会增加查询成本

Rehash操作

Hashmap默认是自动按需扩容,当存入的元素到达阀值时,会对entry数组进行扩容,容量为初始容量的2倍,也就是我们常说的rehash操作

Hashmap线程问题

Hashmap是线程不安全的,所谓的线程不安全就是在多线程情况下会引发诸多问题,如果要在多线程情况下使用map,我们可以有如下几种解决方案。

l  自定义实现hashmap,实现同步机制 // 自己封装

l  使用Map m = Collections.syschronizedMap(new HashMap(…)) // 这里是对hashmap做了封装

l  使用java.util.concurrent.ConcurrentHashMap //安全高效

l  使用hashTable// 不推荐,效率低

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值