Java集合八股-Map

集合两大分支:Collection(包含List和Set)和Map(其下有HashMap-LinkedHashMap,HashTable,TreeMap)

以键值对形式存储数据,大多数以Hash为基本数据结构。

非线程安全:HashMap、LinkedHashMap、TreeMap

线程安全:HashTable、ConcurrentHashMap


HashMap:非线程安全

底层基于Hash实现,根据键的Hash值来存储/获取键值对,之前底层用数组+链表,JDK1.8改为数组+链表+红黑树(详见概念篇)。之前采用头插法,并发时扩容(搬迁数组)可能导致形成环形链表。

环形链表具体表现为:链表A-B-C进行尾插法搬迁,线程1记录A的next为B(内部仅维护一个next,所以只能一个一个记录),此时线程2完成搬迁,新链表为C-B-A。

修改了节点指向:C- next -B- next -A- next -Null,导致B的next为A。之后线程1搬完A之后搬迁B,B搬完之后想要搬C,查询B的next,已经被线程2修改为A,此时就去搬A,搬完A后查询next为null,最终的链表逻辑上就是A-B-A-null,在CPU眼里就是A-B-A-B循环。CPU爆炸

而Java8采用尾插法可以保证next不变,不会导致形成环形链表,但多线程下仍有数据覆盖等问题

依旧可以通过Collection.synchrozied关键字粗暴的包装,但是性能方面不如ConCrurrentHashMap。

LinkedHashMap:非线程安全

继承至HashMap,在此基础上使用双向链表维护顺序。

TreeMap非线程安全

基于红黑树实现的Map,可以对键值对进行排序,但是线程极度不安全,因为多线程插入会破坏红黑树结构。


HashTable:线程安全

简单粗暴,在方法上加synchronized关键字

ConcurrentHashMap:线程安全

底层基于HashMap。之前采用分段锁,将Map中的所有数组(桶)分为几大段,对段上锁,比起对整个Map上锁而言锁粒度更细。

而Java8改为了对桶的头节点用Volatile+CAS或synchronized关键字上锁,也就是对单独一个桶上锁。

具体来说:

添加元素时首先会判断容器是否为空:

  • 如果为空则使用 volatile 加 CAS (比较并替换) 来初始化。
  • 如果容器不为空,则根据存储的元素计算桶是否为空。
  • 如果桶为空,则继续利用 volatile配合CAS设置该节点;
  • 如果桶不为空(Hash碰撞),则使用 synchronized锁住头节点,然后,遍历桶中的数据,并替换或新增节点到桶中,最后再判断是否需要转为红黑树。
  • tips:[CAS经常配合volatile来保证比较部分的数据的实时性]

不可以存null,大部分并发线程安全的集合都不允许null,因为会导致歧义(null or “null”)


Map的遍历方法:forEach、迭代器、Lambda表达式、Stream流等,比较麻烦。

HashMap的put过程:

先计算出Hash值并找到桶的索引。

之后先判断桶内是否为空。

不为空则判断第一个键值对的Hash码和键是否与put的键值对相同(链表O(1))。

不同则遍历链表或红黑树,寻找Hash码和键的equals()是否相同。

找到则覆盖,否则就新插入。

检查链表长度,是否需要树化。检查是否需要扩容。

HashMap的扩容机制:

HashMap的默认扩容因子是0.75,当需要扩容时,将哈希表翻一倍并且将旧的哈希表搬迁到新的哈希表中。

在Java8之前,需要对所有元素进行Hash计算然后重新分配,性能差。

Java8之后则进行优化:

因为哈希表长度翻倍,根据Hash函数公式而参与运算的二进制会多一位。

所以运算所得的hash值只需要判断新的一位是0还是1就可以了,0则保留原位,1则搬迁,性能优化很大

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇