HashMap源碼詳解與對比

来源:https://www.cnblogs.com/fn-f/archive/2019/03/26/10603935.html
-Advertisement-
Play Games

前幾天工作忙得焦頭爛額時,同事問了一下關於Map的特性,剎那間懵了一下,緊接著就想起來了一些關於Map的一些知識,因為只要涉及到Collection集合類時,就會談及Map類,因此理解好Map相關的知識是灰常重要的。 Collection集合類 與 Map類的層次結構,如下圖: Map是用來存儲 K ...


 

  前幾天工作忙得焦頭爛額時,同事問了一下關於Map的特性,剎那間懵了一下,緊接著就想起來了一些關於Map的一些知識,因為只要涉及到Collection集合類時,就會談及Map類,因此理解好Map相關的知識是灰常重要的。

 

  Collection集合類 與 Map類的層次結構,如下圖:

  

 

  Map是用來存儲 Key-Value(K-V)鍵值對,且不允許Key重覆。(JDK 1.8)

  Map的子類包含Hashtable,HashMap,LinkedHashMap,TreeMap,EnumMap,J.U.C併發包下麵包含ConcurrentHashMap,ConcurrentSkipListMap。

  註:Hashtable是通過“synchronized”來實現同步,ConcurrentHashMap是通過“分段鎖”來實現併發,ConcurrentSkipListMap是通過“跳錶”來實現併發。

 

  數據結構對比

  JDK 1.7及之前,HashMap的底層是數組和鏈表結合使用,可以說其結構是單向鏈表構成的數組,即鏈表散列,又稱拉鏈法,即數組中的每一個序列空間代表一鏈表,若在插入新元素時,如果哈希衝突,則將新的元素插入到衝突的序列空間的鏈表頭部。 

   

 

    JDK 1.8之後,HashMap的底層是數組鏈表和二叉樹結合使用,其結構是先以鏈表結構進行存儲,如果當鏈表的節點數(閾值)大於等於8時,再將其轉換為二叉樹結構,若該二叉樹結構的節點數大於64,則再次resize,觸發rehash操作,重新分佈節點

   

 

     JDK 1.7 | 1.8    HashMap 方法分析

  

  1. hashmap在JDK1.7|1.8中hash()方法優化:此處參考博客鏈接_hashmap衝突的解決方法以及原理分析

    其實關於hash優化以及為什麼是2的次冪,能理解,但是總歸沒有辣麽詳細,所以就參考了其他博主的博客,如果不合適,還請提出,會進行刪除的。

     

 

  2. hashmap在JDK中resize()方法

          當HashMap的長度超過臨界值時(預設16*0.75=12),就會進行擴容。

      通過調用resize()方法重新創建一個原HashMap大小的兩倍的元素數組newTable,最大擴容到 MAXIMUM_CAPACITY = 1 << 30,並將原先table的元素全部移到newTable裡面,重新計算hash,然後再重新根據hash分配位置。這個過程叫作rehash(最消耗性能的操作),因為它重新調用hash方法找到新的bucket位置。所以創建HashMap的時候,如果能預知元素個數,應儘量指定初始容量,這樣可以提高HashMap的性能,避免重覆resize()、rehash造成的性能損耗。

      若在多線程情況下,多個線程同時出發resize()方法,會造成死迴圈操作

 

  3. hashmap線程不安全,效率高

          HashMap線程是不安全的,如果在多線程環境下,會出現未知異常(謹記)。

   如果要在多線程情況下使用Map,有以下幾種可供選擇:

    ①、使用Hashtable(類中方法全是synchronized,效率特低,沒有過這種);

    ②、使用Collections.synchronizedMap(new HashMap(...));實現,但不建議使用,使用迭代器遍歷的時候修改映射結構容易出錯;

    ③、使用guava中ImmutableMap,它是線程安全的,且方便快捷的組裝鍵值對(建議);

        ImmutableMap<String, Integer> map1 = ImmutableMap.<String, Integer>builder().put("A", 1) .put("B"2) .put("C", 3) .build();

        ImmutableMap<String, Integer> map2 = ImmutableMap .<String, String>of("X", 0);

    ④、使用java.util.concurrent.ConcurrentHashMap,採用分段鎖(JDK1.7) / CAS(JDK1.8)、相對安全,效率高(建議);

 

 

  4. hashmap其他方法解析

   其他方法後續有時間在進行補充...

 

     JDK 中 HashMap 的其他問題

   暫未想到,如有錯誤,還請指正 ...

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 近日,微軟在 Github 上開源了一個 Python 靜態類型檢查工具:pyright ,引起了社區內的多方關註。 微軟在開源項目上的參與力度是越來越大了,不說收購 Github 這種大的戰略野心,只說它家開源的 VS Code 編輯器,在猿界已經割粉無數,連我們 Python 圈的紅人 Kenn ...
  • 一、springboot是什麼? 微服務,應該是近年來最火的概念,越來越多的公司開始使用微服務架構,面試中被問到的微服務的概率很高,不管對技術的追求,還是為了進更好的公司,微服務都是我們開發人員的必須要學習的知識。 那麼微服務究竟是什麼呢? 我們通俗的理解方式就是:微服務化的核心就是將傳統的一站式應 ...
  • package main import ( "database/sql" "fmt" "strings" ) import ( _ "github.com/mattn/go-adodb" ) type Mssql struct { *sql.DB dataSource string database ...
  • 列表方法append()和extend()之間的差異: append:在最後追加對象 結果 [1, 2, 3, [4, 5]] extend:通過追加加迭代中的元素來擴展列表。 結果 [1, 2, 3, 4, 5] 作者:阿裡媽媽 鏈接:www.pythonheidong.com/blog/arti ...
  • 1.本地倉庫和apache-mavenbin.zip的下載與解壓 <1.apache-mavenbin.zip下載網址 2.Maven環境變數配置 <1.MAVEN_HOME <2.PATH 3.環境搭建驗證 4自定義數據倉庫的位置(apache-maven.setting.xml)的配置 ...
  • Spring ioc 叫控制反轉,也就是把創建Bean的動作交給Spring去完成。 spring ioc 流程大致為 定位-> 載入->註冊 先說幾個比較有意思的點 1.Spring中的通過IOC生成的Bean是存放在ConcurrentHashMap中的 2.通過xml配置SpringBean時 ...
  • 一、python中如何創建類? 1. 直接定義類 2. 通過type對象創建 在python中一切都是對象 在上面這張圖中,A是我們平常在python中寫的類,它可以創建一個對象a。其實A這個類也是一個對象,它是type類的對象,可以說type類是用來創建類對象的類,我們平常寫的類都是type類創建 ...
  • 題意 "題目鏈接" 題目鏈接 一種做法是直接用歐拉降冪算出$2^p \pmod{p 1}$然後矩陣快速冪。 但是今天學習了一下二次剩餘,也可以用通項公式+二次剩餘做。 就是我們猜想$5$在這個模數下有二次剩餘,拉個板子發現真的有。 然求出來直接做就行了 cpp include define Pair ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...