HashMap的几个要点

HashMap的几个要点:

1、数据存储的底层数据结构

2、扩容机制 与rehash

3、同步问题(HashMap HashTable ConcurrentHashMap的区别与理解)

 

一、数据结构与存储

1、HashMap底层是通过数组+链表的数据结构实现的。

 

2、整体来看hashMap中所有数据都存于一个数组table中,数组中的每个元素又是一个链表(hash值相同的元素会被放到一个链表中),链表中的每个节点存入的是每次put进去的元素(put进去的元素会被包装成Node节点)。

 

3、在put元素obj时,会根据元素obj的key的hash值,计算其应该被放在数组哪个位置,即数组的下标i(计算方法,i=hash值%数组的长度,算出的余数就是下标i)

3.1、计算出下标i后,看数组中table[i]是为空,若为空,则直接让将obj包装成一个Node节点,赋值给table[i](table[i]=new Node(obj) 代码仅作示意);不为空则,则依次比较table[i]这个链表每个元素的val,若相等,则覆盖。若都不相等,则放到链表的最后。

 

4、为了解决极端情况的hash冲突,jdk1.8引入了红黑树数据结构。当table[i]中的链表节点数大于8时,会将链表转成红黑树进行存储。当节点数小于6时,则会转成链表储存。

 

扩展阅读 https://blog.csdn.net/Dr_Joker/article/details/57101211

 

 

二、扩容机制 与rehash

扩容机制。hashMap中有全负载因子为0.75。当HashMap的size大于等于 table.length*0.75时,会进行扩容。将重新创建一个newTable来进行存储。newTable的length为table.length*2;  扩容后需要进行rehash。

 

rehash

1、新建一个hash桶newTable,size是原hash桶oldTable的两倍。

2、遍历oldTable中的每个元素,重新计算其hash值,并将其放入到newTable中

       2、1 遍历oldTable中的每个元素,(这里的每个元素是链表)

       2、1、1 将链表中的头节点取出,暂存于e中,并将该链表在oldTable中的位置置空。

       2、1、2 取出e.next元素,暂存于next中

       2、1、3 对e进行计算,算出其在newTable中的位置的下标。

       2、1、4 计算出下标后,根据下标,将e元素放入到newTable中(newTable的每个元素是链表,是将e放入到链表的头节点)

       2、1、4 将next赋值于e,进行while循环。

扩展阅读 https://blog.csdn.net/longwoniu/article/details/48781777

 

 

三、同步问题

HashMap是线程不安全的。解决线程不安全的问题有三:

1、HashTable

2、Collections. synchronizedMap(Map)

3、ConcurrentHashMap

 

1和2都是有Map的每个方法上加上了synchronized关键字,以此来保证线程安全

3 创新点在于对Map进行分段加锁,分成16段分别加锁,所以支持16个线程同时进行写操作。在读的时候不受限制。

扩展阅读 https://yemengying.com/2016/05/07/threadsafe-hashmap/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值