<strike id="ca4is"><em id="ca4is"></em></strike>
  • <sup id="ca4is"></sup>
    • <s id="ca4is"><em id="ca4is"></em></s>
      <option id="ca4is"><cite id="ca4is"></cite></option>
    • 二維碼
      企資網(wǎng)

      掃一掃關(guān)注

      當(dāng)前位置: 首頁 » 企資快報(bào) » 服務(wù) » 正文

      HashMap的設(shè)計(jì)與優(yōu)化

      放大字體  縮小字體 發(fā)布日期:2021-08-19 02:00:58    作者:媒體小英    瀏覽次數(shù):27
      導(dǎo)讀

      前言手執(zhí)煙花以謀生 心懷詩意以謀愛不論我是否去記錄,在往昔與未來的無限歲月中,仍會(huì)有人奮起,有人沉淪,有人成為英雄,有人扮演小丑,有人挺身而出,有人迷惘沉淪。但你只需——“在繁華中自律,在落魄中自愈,

      前言

      手執(zhí)煙花以謀生 心懷詩意以謀愛

      不論我是否去記錄,在往昔與未來的無限歲月中,仍會(huì)有人奮起,有人沉淪,有人成為英雄,有人扮演小丑,有人挺身而出,有人迷惘沉淪。但你只需——“在繁華中自律,在落魄中自愈,在謀生的路上不拋棄良知,在謀愛的路上不丟失最嚴(yán),這次我站在風(fēng)中,任你大霧四起。”


      HashMap的設(shè)計(jì)原理

      1. HashMap設(shè)計(jì)思路:
      1. Map是一種以鍵值對(duì)存儲(chǔ)數(shù)據(jù)的容器,而 HashMap 則是借助了鍵值 Key 的 hashcode 值來組織存儲(chǔ),使得可以非常快速和高效地地根據(jù)鍵值 key 進(jìn)行數(shù)據(jù)的存取。
      2. 對(duì)于鍵值對(duì),HashMap 內(nèi)部會(huì)將其封裝成一個(gè)對(duì)應(yīng)的 Entry 對(duì)象,即 Entry 對(duì)象是鍵值對(duì)的組織形式;
      3. 對(duì)于每個(gè)對(duì)象而言,JVM 都會(huì)為其生成一個(gè) hashcode 值。HashMap 在存儲(chǔ)鍵值對(duì) Entry 的時(shí)候,會(huì)根據(jù) Key 的 hashcode 值,以某種映射關(guān)系,決定應(yīng)當(dāng)將這對(duì)鍵值對(duì) Entry 存儲(chǔ)在 HashMap 中的什么位置上;
      4. 當(dāng)通過 Key 值取數(shù)據(jù)的時(shí)候,然后根據(jù) Key 值的 hashcode 和 內(nèi)部映射條件,直接定位到 Key 對(duì)應(yīng)的 Value 值存放在什么位置,可以非常高效地將 Value 值取出。

      HashMap 的哈希函數(shù)設(shè)計(jì)

      hash 函數(shù)是先拿到 key 的 hashcode,是一個(gè)32位的 int 值,然后讓 hashcode 的高16位和低16位進(jìn)行異或操 作

      也叫擾動(dòng)函數(shù),這么設(shè)計(jì)有二點(diǎn)原因

      1. 一定要盡可能降低 hash 碰撞,越分散越好;
      2. 算法一定要盡可能高效,因?yàn)檫@是高頻操作, 因此采用位運(yùn)算;

      什么是Hash?

          Hash,一般翻譯做“散列”,也有直接音譯為“哈希”的,就是把任意長度的 `輸入`,通過散列算法變換成固定長度的 `輸出`,該輸出就是散列值。ok,這樣的定義可能比較抽象。咱們結(jié)合上面提到的方案二的例子一句一句解釋。
    • 比如:人的姓名就是一個(gè)任意長度的輸入。Z-張三 11; L-李四 22;W-王五 33
    • 然后,直接去Z分類里邊兒找,一發(fā)入魂。但是如果出現(xiàn)很多姓名的首字母是Z的人,比如Z-趙六 44、Z-周七 55,當(dāng)我存的電話多起來,我一樣需要找好多次。——我按照姓名的首字母的大寫去進(jìn)行一個(gè)分類,這個(gè)劃分的方式我們可以看成是散列算法。
    • 最后,在本子上以姓名的首字母劃分,并記錄電話號(hào)碼——固定長度的輸出,即我把所有的電話全部存入了26個(gè)分類中。那么這26個(gè)字母就是散列值。

      ? HashMap 的數(shù)據(jù)結(jié)構(gòu)(JDK 1.8)

      本文說的是 JDK1.8 版本的,內(nèi)部使用數(shù)組 + 鏈表紅黑樹

    • 在 Jdk1.8 中 HashMap 的實(shí)現(xiàn)方式做了一些改變,但是基本思想還是沒有變得,只是在一些地方做了 優(yōu)化,下面來看一下這些改變的地方:數(shù)據(jù)結(jié)構(gòu)的存儲(chǔ)由數(shù)組+鏈表的方式,變化為 數(shù)組+鏈表+紅黑樹的存儲(chǔ)方式,當(dāng)鏈表長度超過 閾值(8) 時(shí),將 鏈表轉(zhuǎn)換為紅黑樹。在性能上進(jìn)一步得到提升。
    • 數(shù)組:數(shù)組存儲(chǔ)區(qū)間是連續(xù)的,占用內(nèi)存嚴(yán)重,故空間復(fù)雜度很大。但數(shù)組的二分查找時(shí)間復(fù)雜度小,為O(1);數(shù)組的特點(diǎn)是:尋址容易,插入和刪除困難; 空間復(fù)雜度:指的是執(zhí)行算法所需要的內(nèi)存空間 時(shí)間復(fù)雜度:執(zhí)行算法所需要的計(jì)算工作量
    • 鏈表:鏈表存儲(chǔ)區(qū)間離散,占用內(nèi)存比較寬松,故空間復(fù)雜度很小,但時(shí)間復(fù)雜度很大,達(dá)O(N)。鏈表的特點(diǎn)是:尋址困難,插入和刪除容易。
    • 紅黑樹:

      JDK1.8 對(duì) HashMap 主要做了哪些優(yōu)化呢?

      1. 數(shù)組 + 鏈表改成了數(shù)組 + 鏈表或紅黑樹;
      2. 鏈表的插入方式從頭插法改成了尾插法,簡單說就是插入時(shí),如果數(shù)組位置上已經(jīng)有元素,1.7 將新元 素放到數(shù)組中,原始節(jié)點(diǎn)作為新節(jié)點(diǎn)的后繼節(jié)點(diǎn),1.8 遍歷鏈表,將元素放置到鏈表的最后;
      3. 擴(kuò)容的時(shí)候 1.7 需要對(duì)原數(shù)組中的元素進(jìn)行重新 hash 定位在新數(shù)組的位置,1.8 采用更簡單的判斷邏 輯,位置不變或索引 + 舊容量大小;
      4. 在插入時(shí),1.7 先判斷是否需要擴(kuò)容,再插入,1.8 先進(jìn)行插入,插入完成再判斷是否需要擴(kuò)容;

      ?為什么要做這幾點(diǎn)優(yōu)化

      1. 防止發(fā)生 hash 沖突,鏈表長度過長,將時(shí)間復(fù)雜度由 O(n) 降為 O(logn) ;
      2. 因?yàn)?1.7 頭插法擴(kuò)容時(shí),頭插法會(huì)使鏈表發(fā)生反轉(zhuǎn),多線程環(huán)境下會(huì)產(chǎn)生環(huán); A 線程在插入節(jié)點(diǎn) B,B 線程也在插入,遇到容量不夠開始擴(kuò)容,重新 hash,放置元素,采用頭插法, 后遍歷到的 B 節(jié)點(diǎn)放入了頭部,這樣形成了環(huán),如下圖所示:

      1.7 的擴(kuò)容調(diào)用 transfer 代碼,如下所示:

      void transfer(Entry[] newTable, boolean rehash) {int newCapacity = newTable.length;for (Entry<K,V> e : table) {while(null != e) {Entry<K,V> next = e.next;if (rehash) {e.hash = null == e.key ? 0 : hash(e.key);} int i = indexFor(e.hash, newCapacity);e.next = newTable[i]; //A線程如果執(zhí)行到這一行掛起,B線程開始進(jìn)行擴(kuò)容newTable[i] = e;e = next;}}}  
      1. 擴(kuò)容的時(shí)候?yàn)槭裁?1.8 不用重新 hash 就可以直接定位原節(jié)點(diǎn)在新數(shù)據(jù)的位置 這是由于擴(kuò)容是擴(kuò)大為原數(shù)組大小的 2 倍,用于計(jì)算數(shù)組位置的掩碼僅僅只是高位多了一個(gè) 1,怎么理 解呢? 擴(kuò)容前長度為 16,用于計(jì)算 (n-1) & hash 的二進(jìn)制 n-1 為 0000 1111,擴(kuò)容為 32 后的二進(jìn)制就高位多 了 1,為 0001 1111。 因?yàn)槭?& 運(yùn)算,1 和任何數(shù) & 都是她本身,那就分二種情況,如下圖:原數(shù)據(jù) hashcode 高位第 4 位為 0 和高位為 1 的情況; 第四位高位為 0,重新 hash 數(shù)值不變,第四位為 1,重新 hash 數(shù)值比原來大 16(舊數(shù)組的容量)
    •  
      (文/媒體小英)
      免責(zé)聲明
      本文僅代表作發(fā)布者:媒體小英個(gè)人觀點(diǎn),本站未對(duì)其內(nèi)容進(jìn)行核實(shí),請(qǐng)讀者僅做參考,如若文中涉及有違公德、觸犯法律的內(nèi)容,一經(jīng)發(fā)現(xiàn),立即刪除,需自行承擔(dān)相應(yīng)責(zé)任。涉及到版權(quán)或其他問題,請(qǐng)及時(shí)聯(lián)系我們刪除處理郵件:weilaitui@qq.com。
       

      Copyright ? 2016 - 2025 - 企資網(wǎng) 48903.COM All Rights Reserved 粵公網(wǎng)安備 44030702000589號(hào)

      粵ICP備16078936號(hào)

      微信

      關(guān)注
      微信

      微信二維碼

      WAP二維碼

      客服

      聯(lián)系
      客服

      聯(lián)系客服:

      在線QQ: 303377504

      客服電話: 020-82301567

      E_mail郵箱: weilaitui@qq.com

      微信公眾號(hào): weishitui

      客服001 客服002 客服003

      工作時(shí)間:

      周一至周五: 09:00 - 18:00

      反饋

      用戶
      反饋

      午夜久久久久久网站,99久久www免费,欧美日本日韩aⅴ在线视频,东京干手机福利视频
        <strike id="ca4is"><em id="ca4is"></em></strike>
      • <sup id="ca4is"></sup>
        • <s id="ca4is"><em id="ca4is"></em></s>
          <option id="ca4is"><cite id="ca4is"></cite></option>
        • 主站蜘蛛池模板: 高清国产性色视频在线| 久久99精品久久久久久不卡| 131美女爽爽爽爱做视频| 欧美色欧美亚洲高清在线观看 | 免费观看男男污污ww网站| 丰满年轻的继坶| 色多多在线观看| 成年片色大黄全免费网站久久| 国产91在线看| 三上悠亚ssni_229在线播放| 美女激情视频网站| 巨胸喷奶水视频www网快速| 再灬再灬再灬深一点舒服| yy6080欧美三级理论| 狠狠噜狠狠狠狠丁香五月| 外国毛片大全免费看| 亚洲片在线观看| 2022国产成人福利精品视频| 欧洲最强rapper网站在线看| 国产日产欧美精品| 久久人妻少妇嫩草av蜜桃| 色偷偷888欧美精品久久久| 成人a在线观看| 伊人不卡久久大香线蕉综合影院| 99国产欧美久久久精品| 欧美日韩三级在线观看| 国产真乱全集mangent| 久久夜色精品国产网站| 翁想房中春意浓1-28| 好男人官网在线播放| 亚洲精品成人av在线| xx视频在线永久免费观看| 日本精品视频在线播放| 又粗又猛又黄又爽无遮挡| avove尤物| 欧美国产在线看| 国产午夜免费秋霞影院| 一级做a爰片性色毛片新版的| 波多野结衣第一页| 国产欧美一区二区另类精品| 丰满亚洲大尺度无码无码专线|