Java 集合

1. ArrayList LinkedList

2. ArrayList 擴(kuò)容機(jī)制

3. HashSet

4. HashMap 和 HashTable 區(qū)別

線程是否安全
效率
初始容量 和 每次擴(kuò)容的大小
底層數(shù)據(jù)結(jié)構(gòu)

5. HashMap 底層實(shí)現(xiàn)

5.1

1.8 之前 數(shù)組+鏈表
1.8 數(shù)組+鏈表+紅黑樹

相比于之前的版本, JDK1.8 之后在解決哈希沖突時(shí)有了較大的變化,當(dāng)鏈表長(zhǎng)度大于閾值(默認(rèn)為 8)(將鏈表轉(zhuǎn)換成紅黑樹前會(huì)判斷猫十,如果當(dāng)前數(shù)組的長(zhǎng)度小于 64挖垛,那么會(huì)選擇先進(jìn)行數(shù)組擴(kuò)容警检,而不是轉(zhuǎn)換為紅黑樹)時(shí),將鏈表轉(zhuǎn)化為紅黑樹误墓,以減少搜索時(shí)間唁影。

TreeMap、TreeSet 以及 JDK1.8 之后的 HashMap 底層都用到了紅黑樹遇伞。紅黑樹就是為了解決二叉查找樹的缺陷辙喂,因?yàn)槎娌檎覙湓谀承┣闆r下會(huì)退化成一個(gè)線性結(jié)構(gòu)。

5.2HashMap 的長(zhǎng)度為什么是2的冪次方

為了能讓 HashMap 存取高效,盡量較少碰撞加派,也就是要盡量把數(shù)據(jù)分配均勻叫确。我們上面也講到了過(guò)了,Hash 值的范圍值-2147483648到2147483647芍锦,前后加起來(lái)大概40億的映射空間竹勉,只要哈希函數(shù)映射得比較均勻松散,一般應(yīng)用是很難出現(xiàn)碰撞的娄琉。但問題是一個(gè)40億長(zhǎng)度的數(shù)組次乓,內(nèi)存是放不下的。所以這個(gè)散列值是不能直接拿來(lái)用的孽水。用之前還要先做對(duì)數(shù)組的長(zhǎng)度取模運(yùn)算票腰,得到的余數(shù)才能用來(lái)要存放的位置也就是對(duì)應(yīng)的數(shù)組下標(biāo)。這個(gè)數(shù)組下標(biāo)的計(jì)算方法是“ (n - 1) & hash”女气。(n代表數(shù)組長(zhǎng)度)杏慰。這也就解釋了 HashMap 的長(zhǎng)度為什么是2的冪次方。

5.3 HashMap 多線程操作導(dǎo)致死循環(huán)問題

主要原因在于 并發(fā)下的Rehash 會(huì)造成元素之間會(huì)形成一個(gè)循環(huán)鏈表炼鞠。不過(guò)缘滥,jdk 1.8 后解決了這個(gè)問題,但是還是不建議在多線程下使用 HashMap,因?yàn)槎嗑€程下使用 HashMap 還是會(huì)存在其他問題比如數(shù)據(jù)丟失谒主。并發(fā)環(huán)境下推薦使用 ConcurrentHashMap 朝扼。

5.4 ConcurrentHashMap 和 Hashtable 的區(qū)別

ConcurrentHashMap 和 Hashtable 的區(qū)別主要體現(xiàn)在實(shí)現(xiàn)線程安全的方式上不同。

  1. 底層數(shù)據(jù)結(jié)構(gòu): JDK1.7 的 ConcurrentHashMap 底層采用 分段的數(shù)組+鏈表 實(shí)現(xiàn)霎肯,JDK1.8 采用的數(shù)據(jù)結(jié)構(gòu)跟 HashMap1.8 的結(jié)構(gòu)一樣擎颖,數(shù)組+鏈表/紅黑二叉樹。Hashtable 和 JDK1.8 之前的 HashMap 的底層數(shù)據(jù)結(jié)構(gòu)類似都是采用 數(shù)組+鏈表 的形式观游,數(shù)組是 HashMap 的主體搂捧,鏈表則是主要為了解決哈希沖突而存在的;
  2. 實(shí)現(xiàn)線程安全的方式(重要): ① 在 JDK1.7 的時(shí)候备典,ConcurrentHashMap(分段鎖) 對(duì)整個(gè)桶數(shù)組進(jìn)行了分割分段(Segment)异旧,每一把鎖只鎖容器其中一部分?jǐn)?shù)據(jù),多線程訪問容器里不同數(shù)據(jù)段的數(shù)據(jù)提佣,就不會(huì)存在鎖競(jìng)爭(zhēng)吮蛹,提高并發(fā)訪問率。 到了 JDK1.8 的時(shí)候已經(jīng)摒棄了 Segment 的概念拌屏,而是直接用 Node 數(shù)組+鏈表+紅黑樹的數(shù)據(jù)結(jié)構(gòu)來(lái)實(shí)現(xiàn)潮针,并發(fā)控制使用 synchronized 和 CAS 來(lái)操作。(JDK1.6 以后 對(duì) synchronized 鎖做了很多優(yōu)化) 整個(gè)看起來(lái)就像是優(yōu)化過(guò)且線程安全的 HashMap倚喂,雖然在 JDK1.8 中還能看到 Segment 的數(shù)據(jù)結(jié)構(gòu)每篷,但是已經(jīng)簡(jiǎn)化了屬性瓣戚,只是為了兼容舊版本;② Hashtable(同一把鎖) :使用 synchronized 來(lái)保證線程安全焦读,效率非常低下子库。當(dāng)一個(gè)線程訪問同步方法時(shí),其他線程也訪問同步方法矗晃,可能會(huì)進(jìn)入阻塞或輪詢狀態(tài)仑嗅,如使用 put 添加元素,另一個(gè)線程不能使用 put 添加元素张症,也不能使用 get仓技,競(jìng)爭(zhēng)會(huì)越來(lái)越激烈效率越低。

6. ConcurrentHashMap線程安全的具體實(shí)現(xiàn)方式/底層具體實(shí)現(xiàn)

6.1 JDK1.7時(shí)

首先將數(shù)據(jù)分為一段一段的存儲(chǔ)俗他,然后給每一段數(shù)據(jù)配一把鎖脖捻,當(dāng)一個(gè)線程占用鎖訪問其中一個(gè)段數(shù)據(jù)時(shí),其他段的數(shù)據(jù)也能被其他線程訪問兆衅。

ConcurrentHashMap 是由 Segment 數(shù)組結(jié)構(gòu)和 HashEntry 數(shù)組結(jié)構(gòu)組成地沮。

Segment 實(shí)現(xiàn)了 ReentrantLock,所以 Segment 是一種可重入鎖,扮演鎖的角色涯保。HashEntry 用于存儲(chǔ)鍵值對(duì)數(shù)據(jù)诉濒。

一個(gè) ConcurrentHashMap 里包含一個(gè) Segment 數(shù)組周伦。Segment 的結(jié)構(gòu)和 HashMap 類似夕春,是一種數(shù)組和鏈表結(jié)構(gòu),一個(gè) Segment 包含一個(gè) HashEntry 數(shù)組专挪,每個(gè) HashEntry 是一個(gè)鏈表結(jié)構(gòu)的元素及志,每個(gè) Segment 守護(hù)著一個(gè) HashEntry 數(shù)組里的元素,當(dāng)對(duì) HashEntry 數(shù)組的數(shù)據(jù)進(jìn)行修改時(shí)寨腔,必須首先獲得對(duì)應(yīng)的 Segment 的鎖速侈。

6.2 JDK1.8時(shí)

ConcurrentHashMap 取消了 Segment 分段鎖,采用 CAS 和 synchronized 來(lái)保證并發(fā)安全迫卢。數(shù)據(jù)結(jié)構(gòu)跟 HashMap1.8 的結(jié)構(gòu)類似倚搬,數(shù)組+鏈表/紅黑二叉樹。Java 8 在鏈表長(zhǎng)度超過(guò)一定閾值(8)時(shí)將鏈表(尋址時(shí)間復(fù)雜度為 O(N))轉(zhuǎn)換為紅黑樹(尋址時(shí)間復(fù)雜度為 O(log(N)))

synchronized 只鎖定當(dāng)前鏈表或紅黑二叉樹的首節(jié)點(diǎn)乾蛤,這樣只要 hash 不沖突每界,就不會(huì)產(chǎn)生并發(fā),效率又提升 N 倍家卖。

7. CAS(Compare-and-Swap)

即比較并替換眨层,是一種實(shí)現(xiàn)并發(fā)算法時(shí)常用到的技術(shù),Java并發(fā)包中的很多類都使用了CAS技術(shù)上荡。
Java 中的各種鎖和 CAS + 面試題
從 Atomic 到 CAS

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末趴樱,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌叁征,老刑警劉巖纳账,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異捺疼,居然都是意外死亡塞祈,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門帅涂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)议薪,“玉大人,你說(shuō)我怎么就攤上這事媳友∷挂椋” “怎么了?”我有些...
    開封第一講書人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵醇锚,是天一觀的道長(zhǎng)哼御。 經(jīng)常有香客問我,道長(zhǎng)焊唬,這世上最難降的妖魔是什么恋昼? 我笑而不...
    開封第一講書人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮赶促,結(jié)果婚禮上液肌,老公的妹妹穿的比我還像新娘。我一直安慰自己鸥滨,他們只是感情好嗦哆,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著婿滓,像睡著了一般老速。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上凸主,一...
    開封第一講書人閱讀 51,443評(píng)論 1 302
  • 那天橘券,我揣著相機(jī)與錄音,去河邊找鬼卿吐。 笑死旁舰,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的但两。 我是一名探鬼主播鬓梅,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼谨湘!你這毒婦竟也來(lái)了绽快?” 一聲冷哼從身側(cè)響起芥丧,我...
    開封第一講書人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎坊罢,沒想到半個(gè)月后续担,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡活孩,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年物遇,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片憾儒。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡询兴,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出起趾,到底是詐尸還是另有隱情诗舰,我是刑警寧澤,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布训裆,位于F島的核電站眶根,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏边琉。R本人自食惡果不足惜属百,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望变姨。 院中可真熱鬧族扰,春花似錦、人聲如沸钳恕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)忧额。三九已至,卻和暖如春愧口,著一層夾襖步出監(jiān)牢的瞬間睦番,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工耍属, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留托嚣,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓厚骗,卻偏偏與公主長(zhǎng)得像示启,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子领舰,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 「我是大廠面試官」—— Java 集合,你肯定會(huì)被問到這些 文章收錄在 GitHub JavaKeeper 舍咖,N線...
    JavaKeeper_海星閱讀 386評(píng)論 0 1
  • 文章目錄集合容器概述什么是集合集合的特點(diǎn)集合和數(shù)組的區(qū)別使用集合框架的好處常用的集合類有哪些矩父?List,Set排霉,M...
    灬佐手邊閱讀 344評(píng)論 0 1
  • ArrayList和LinkedList區(qū)別窍株? 1.是否保證線程安全: ArrayList和LinkedList都...
    Z_acad閱讀 336評(píng)論 0 0
  • 剛剛經(jīng)歷過(guò)秋招,看了大量的面經(jīng)攻柠,順便將常見的Java集合城蚨考知識(shí)點(diǎn)總結(jié)了一下,并根據(jù)被問到的頻率大致做了一個(gè)標(biāo)注瑰钮。...
    dybaby閱讀 288評(píng)論 0 3
  • 什么是集合 集合框架:用于存儲(chǔ)數(shù)據(jù)的容器辙售。 集合框架是為表示和操作集合而規(guī)定的一種統(tǒng)一的標(biāo)準(zhǔn)的體系結(jié)構(gòu)。 任何集合...
    Java__JJ閱讀 265評(píng)論 0 1