免费人成动漫在线播放r18-免费人成观看在线网-免费人成黄页在线观看日本-免费人成激情视频在线观看冫-jlzzjlzz亚洲大全-jlzzjlzz亚洲日本

二維碼
企資網(wǎng)

掃一掃關(guān)注

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

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

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

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

前言

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

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


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

1. HashMap設(shè)計(jì)思路:
  1. Map是一種以鍵值對(duì)存儲(chǔ)數(shù)據(jù)的容器,而 HashMap 則是借助了鍵值 Key 的 hashcode 值來(lái)組織存儲(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)通過(guò) 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,一般翻譯做“散列”,也有直接音譯為“哈希”的,就是把任意長(zhǎng)度的 `輸入`,通過(guò)散列算法變換成固定長(zhǎng)度的 `輸出`,該輸出就是散列值。ok,這樣的定義可能比較抽象。咱們結(jié)合上面提到的方案二的例子一句一句解釋。
  • 比如:人的姓名就是一個(gè)任意長(zhǎng)度的輸入。Z-張三 11; L-李四 22;W-王五 33
  • 然后,直接去Z分類里邊兒找,一發(fā)入魂。但是如果出現(xiàn)很多姓名的首字母是Z的人,比如Z-趙六 44、Z-周七 55,當(dāng)我存的電話多起來(lái),我一樣需要找好多次。——我按照姓名的首字母的大寫去進(jìn)行一個(gè)分類,這個(gè)劃分的方式我們可以看成是散列算法。
  • 最后,在本子上以姓名的首字母劃分,并記錄電話號(hào)碼——固定長(zhǎng)度的輸出,即我把所有的電話全部存入了26個(gè)分類中。那么這26個(gè)字母就是散列值。

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

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

  • 在 Jdk1.8 中 HashMap 的實(shí)現(xiàn)方式做了一些改變,但是基本思想還是沒(méi)有變得,只是在一些地方做了 優(yōu)化,下面來(lái)看一下這些改變的地方:數(shù)據(jù)結(jié)構(gòu)的存儲(chǔ)由數(shù)組+鏈表的方式,變化為 數(shù)組+鏈表+紅黑樹(shù)的存儲(chǔ)方式,當(dāng)鏈表長(zhǎng)度超過(guò) 閾值(8) 時(shí),將 鏈表轉(zhuǎn)換為紅黑樹(shù)。在性能上進(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)是:尋址困難,插入和刪除容易。
  • 紅黑樹(shù):

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

    1. 數(shù)組 + 鏈表改成了數(shù)組 + 鏈表或紅黑樹(shù);
    2. 鏈表的插入方式從頭插法改成了尾插法,簡(jiǎn)單說(shuō)就是插入時(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 采用更簡(jiǎn)單的判斷邏 輯,位置不變或索引 + 舊容量大小;
    4. 在插入時(shí),1.7 先判斷是否需要擴(kuò)容,再插入,1.8 先進(jìn)行插入,插入完成再判斷是否需要擴(kuò)容;

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

    1. 防止發(fā)生 hash 沖突,鏈表長(zhǎng)度過(guò)長(zhǎng),將時(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 線程也在插入,遇到容量不夠開(kāi)始擴(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線程開(kāi)始進(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ò)容前長(zhǎng)度為 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ù)值比原來(lái)大 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)或其他問(wè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

    反饋

    用戶
    反饋

    主站蜘蛛池模板: 天天色天天射综合网 | 先锋资源av| 91最新免费地址入口 | 国产日韩精品欧美一区喷水 | 麒麟色欧美影院在线播放 | 国产黄色毛片视频 | 狠狠躁狠狠躁 | 男女生性毛片免费观看 | 日本三级香港三级人妇99 | 亚洲精品免费在线视频 | 久久xxxx| 九九精品免视频国产成人 | 插菊花综合 | 狠狠色综合久久久久尤物 | 人人爽人人干 | 2021国产精品自在拍在线播放 | 91国内外精品自在线播放 | 一级欧美在线的视频 | 久久天天躁狠狠躁夜夜免费观看 | 亚洲欧美v视色一区二区 | 成人黄色一级毛片 | 久久亚洲最大成人网4438 | 日韩精品免费在线观看 | 日本人xxxⅹ18hd18hd | 狠狠色欧美亚洲狠狠色五 | 一区二区三区 日韩 | 午夜黄视频 | 热门国产xvideos中文 | 日本全身露裸无遮挡黄漫画 | 国产成人亚洲毛片 | 亚洲伦理精品久久 | 美女很黄很黄的网站 | 天天做天天爱天天操 | xxxxxx日本护士xxxx | 日韩欧美亚洲中字幕在线播放 | 国产大臿蕉香蕉大视频女 | 日日噜噜夜夜狠狠久久aⅴ 日日噜噜夜夜狠狠久久丁香七 | 国产一国产一有一级毛片 | 国产偷国产偷亚洲高清在线 | 久青草国产在线视频_久青草免 | 欧美国产成人一区二区三区 |