HashMap底层原理和保证线程安全的方法

HashMap的底层原理

  1. 先计算出key对应的hashcode
  2. 通过hash(key)%len得到要插入的数组节点(哈希表的数组的初始长度为16),
  3. 插入:如果key的hashCode重复(即:数组的下标重复),则将新的key和旧的key放到链表中。如果key值一样,进行数据覆盖:(JDK7是头插法;JDK8是尾插法);
    ps:若链表长度大于8 且容量小于64 会进行扩容;若链表长度大于8 且数组长度大于等于64,会转化为红黑树(提高定位元素的速度);若红黑树节点个数小于6,则将红黑树转为链表
    在这里插入图片描述
    例如:
    有几个key的hashcode分别为12、28、108、140,由于12%16=12;28%16=12;108%16=12;140%16=12,因此均插入到数组下标为12的链表中。
    在这里插入图片描述

HashMap扩容的原理

HashMap是懒加载,构造完HashMap对象后,若没用 put 来插入元素,HashMap不会去初始化或者扩容table。扩容的场景如下:

  1. 首次调用put方法时,HashMap会发现table为空然后调用resize方法进行初始化。
  2. 非首次调用put方法时,若HashMap发现size(元素个数)大于threshold(阈值)(数组长度乘以加载因子的值),则会调用resize方法进行扩容。
  3. 链表长度大于8 且数组长度小于64 会进行扩容。链表长度大于8 (且数组长度大于等于64),会转化为红黑树。
    数组是无法自动扩容的,所以只能是换一个更大的数组去装填以前的元素和将要添加的新元素。

resize()方法扩容的判断:

  1. 判断扩容前的旧数组容量是否已经达到最大(2^30)了
    • 若达到则修改阈值为Integer的最大值(2^31 – 1),以后就不会扩容了。
    • 若没达到,则修改数组大小为原来的2倍
  2. 以新数组大小创建新的数组(Node<K, V>[])
  3. 将数据转移到新的数组(Node[])里
    不一定所有的节点都要换位置。比如:原数组大小为16,扩容后为32。若原来有hash值为1和17两个数据,他们对16取余都是1,在同一个桶里;扩容后,1对32取余仍然是1,而17对32取余却成了17,需要换个位置。(对应的代码为:if ((e.hash & oldCap) == 0) 若为true,则不需要换位置。
    返回新的Node<K, V>[] 数组

HashMap保证线程安全的方法

在这里插入图片描述
线程不安全的原因:key值相同时会进行数据覆盖。

HashMap,TreeMap,LinkedHashMap的区别

在这里插入图片描述

详细可参考源码或者自学自学精灵

  • 21
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
HashMap实现原理是基于哈希表(Hash Table)的数据结构。在HashMap中,每个元素被存储为键值对(key-value pair),通过计算键的哈希值来确定其在数组中的存储位置。 具体实现原理如下: 1. 当我们向HashMap中插入一个键值对时,首先会计算键的哈希值。 2. 根据哈希值,HashMap使用哈希函数将其转换为一个数组索引。 3. 如果该索引处没有元素,则直接将键值对插入该位置。 4. 如果该索引处已经存在元素,则发生冲突,HashMap会使用链表或者红黑树的方式来处理冲突(JDK 8之后,如果链表长度超过阈值(默认为8),链表会转换为红黑树)。 5. 当需要查找元素时,HashMap会根据键的哈希值找到对应的数组索引,并在该位置上进行查找。 HashMap如何保证线程安全取决于具体的使用场景和需求。如果在多线程环境下使用HashMap,并且涉及到插入、删除、修改等操作,可以考虑以下几种方式来保证线程安全: 1. 使用ConcurrentHashMap:ConcurrentHashMapJava提供的线程安全的哈希表实现。它使用了分段锁(Segment)的机制来保证并发访问的安全性,可以支持高并发的读操作和部分并发的写操作。 2. 使用Collections.synchronizedMap()方法:通过该方法可以将HashMap转换为线程安全的Map,底层使用了同步块(synchronized block)来保证线程安全。例如:Map<String, String> synchronizedMap = Collections.synchronizedMap(new HashMap<>()); 3. 使用锁机制:在多线程环境下,可以使用显式的锁机制(如ReentrantLock、synchronized等)来对HashMap进行加锁,保证每次操作的原子性和互斥性。 需要注意的是,即使采取了上述措施来保证HashMap线程安全性,也需要根据具体业务场景考虑并发读写带来的性能影响。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值