Map底层原理解析

Map
  1. 采用了数组加链表的方式存储(横向数组,纵向链表),当有同一hash值得数据会被房到同意数组后面形成链表
HashMap(默认16长度)
  1. put
int hash = hash(key); 获取hash值
int i = indexFor(hash, table.length);  tab[hash&(n-1)]返回Map table索引位置(为了解决均匀散列索引)
循环遍历链表,如果当前Entry hash值与key跟传入的key相等则将新值赋值给旧值,返回旧值
否则创建新的Entry,并将空的tab[hash&(n-1)]赋值给Entry.next
  1. get
<1>计算hash值
<2>遍历链表,根据int i = indexFor(hash, table.length);Map table数组索引值位置
HashTable(默认11长度)
  1. HashTable使用了synchronized进行加锁

  2. int hash = hash(key);获取该key的哈希值

  3. int index = (hash & 0x7FFFFFFF) % tab.length; 获取该key在table数组的索引下标,得到该索引下的链表

ConcurrentHashMap(默认16长度的Segment(段),16个并发)

初始化:默认初始化16段(Segment),16个并发数,在第一段初始化长度为2的HashEntry数组(主要作用是保存第一次初始化的时候的参数如:长度,扩展阈值)

   在操作put与get的时候使用了Unsafe非阻塞同步机制(基于硬件级别的CAS算法),Segment操作时会经过两次hash运算,
   
   第一次hash:(hash(key) >>> segmentShift(28)) & segmentMask(15)得到Segment的位置
   
   第二次hash是用第一次hash值的基础上(tab.length - 1) & hash得到HashEntry数组的索引,从而得到链表
  1. ConcurrentHashMap结构为先分为16个Segment段,在每个Segment再已横向HashEntry数组,再纵向链表的形式保存数据,
    操作是采用ReentrantLock锁住一个Segment里面HashEntry,保证线程安全而不会锁住整个Map

  2. put操作
    先获取key的hash值计算该key在Segment位置

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值