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

被折叠的 条评论
为什么被折叠?



