欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java中對(duì)HashMap的put過(guò)程解讀

 更新時(shí)間:2023年03月22日 16:05:14   作者:新時(shí)代的農(nóng)民工  
這篇文章主要介紹了java中對(duì)HashMap的put過(guò)程解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

HashMap解析put的過(guò)程

首先,用代碼運(yùn)行下,來(lái)體會(huì)下:

代碼實(shí)現(xiàn):

@Test
	public void test1() {
		//創(chuàng)建了一個(gè)HashMap
		Map<String,Object>map = new HashMap<>();

		//使用put方法保存數(shù)據(jù)
		map.put("age", 12);
		map.put("name", "gaga");
		
		System.out.println(map);
		}

運(yùn)行結(jié)果:

首先經(jīng)過(guò)了hash之后的key,是一個(gè)整型的hashcode,其次是我們傳入的key和value。

首先一進(jìn)入putVal就會(huì)聲明存放數(shù)據(jù)的table,如果這個(gè)HashMap是首次設(shè)置值,就會(huì)被初始化一個(gè)默認(rèn)size的table,且所有元素的初始值都是NULL。

默認(rèn)值為啥是16

通過(guò)源碼解析,在注釋中會(huì)得到“The default initial capacity - MUST be a power of two.”意思是:默認(rèn)初始容量-必須是2的冪。

自動(dòng)擴(kuò)容

除了size,初始化的時(shí)候還會(huì)設(shè)定一個(gè)閾值,值為12,newThr = 12,這里需要提到一個(gè)概念負(fù)載因子,HashMap的實(shí)現(xiàn)里默認(rèn)給的是0.75。

負(fù)載因子是用來(lái)干嘛的呢?當(dāng)我們不停的往map里存數(shù)據(jù)的時(shí)候,總會(huì)存滿(mǎn),當(dāng)元素快存滿(mǎn)的時(shí)候,我們就需要擴(kuò)大map的容量,來(lái)容納更多的元素,這就需要一個(gè)自動(dòng)擴(kuò)容的機(jī)制了。

在當(dāng)數(shù)據(jù)量大于超過(guò)設(shè)定的閾值的時(shí)候(容量*負(fù)載因子),自動(dòng)對(duì)map進(jìn)行擴(kuò)容,以存放更多的數(shù)據(jù)。

自動(dòng)擴(kuò)容做了什么事情呢?

  • 1、創(chuàng)建新的數(shù)組,大小是原來(lái)數(shù)組的一倍。
  • 2、將元素rehash到新的數(shù)組

為什么要rehash呢?上面我們提到過(guò)了,當(dāng)元素被放進(jìn)map時(shí),確認(rèn)下標(biāo)的方法是table的長(zhǎng)度-1和hash值做與運(yùn)算,現(xiàn)在table的長(zhǎng)度發(fā)生了變化,那么自然而然,元素獲取下標(biāo)的運(yùn)算結(jié)果也就跟之前的不一樣了, 所以需要將老的map中的元素再按照新的table長(zhǎng)度rehash到擴(kuò)容后的table中。

put的過(guò)程

了解了底層數(shù)據(jù)結(jié)構(gòu)和自動(dòng)擴(kuò)容機(jī)制,接下來(lái)我們來(lái)看一下put過(guò)程中究竟發(fā)生了什么。

我們上面說(shuō)過(guò)了,會(huì)通過(guò)數(shù)組的長(zhǎng)度-1和hash值與運(yùn)算得到一個(gè)數(shù)組下標(biāo)。

如果該位置沒(méi)有元素,那么就很簡(jiǎn)單,直接新建一個(gè)節(jié)點(diǎn)即可然后放置在數(shù)據(jù)的具體位置即可。

tab[i] = this.newNode(hash, key, value, (HashMap.Node)null);

但是如果該下標(biāo)已經(jīng)有元素了,這種情況HashMap是怎么處理的呢?這也要看情況。

如果是跟當(dāng)前槽位相同的key,就直接覆蓋。這就是我們修改某個(gè)key的值會(huì)發(fā)生的情況。

那HashMap怎么來(lái)判斷是不是同一個(gè)key呢?

就像下面這樣。p就是當(dāng)前槽位上已經(jīng)有的元素,如果新、老元素的key的hashCode和值都相同且key不為空,那么就能證明這兩個(gè)key是相同的,那么此時(shí)只需要覆蓋即可。

p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))

而如果p是TreeNode的實(shí)例,那么就代表當(dāng)前槽位已經(jīng)是一個(gè)紅黑樹(shù)了,此時(shí)只需要往這個(gè)樹(shù)里putTreeVal即可。

至于為什么是紅黑樹(shù),哪兒來(lái)的紅黑樹(shù),下面馬上就要講到了。

最后一種情況就是,既不是已經(jīng)存在的元素也不是TreeNode的實(shí)例,也不是紅黑樹(shù)。這種情況下,它就是一個(gè)普通的Node。

你可以理解為鏈表,如果hash沖突了,就把這個(gè)Node放到該位置的鏈表末尾。

當(dāng)該位置的鏈表中的元素超過(guò)了TREEIFY_THRESHOLD所設(shè)置的數(shù)量時(shí),就會(huì)觸發(fā)樹(shù)化,將其轉(zhuǎn)化為紅黑樹(shù)。Java8里給的默認(rèn)值是8。

為啥要轉(zhuǎn)化成紅黑樹(shù)?

首先我們要知道為什么要樹(shù)化。

當(dāng)大量的數(shù)據(jù)放入Map中,Hash沖突會(huì)越來(lái)越多,某些位置就會(huì)出現(xiàn)一個(gè)很長(zhǎng)的鏈表的情況。

這種情況下,查詢(xún)時(shí)間復(fù)雜度是O(n) ,刪除的時(shí)間復(fù)雜度也是O(n),查詢(xún)、刪除的效率會(huì)大大降低。

而同樣的數(shù)據(jù)情況下,平衡二叉樹(shù)的時(shí)間復(fù)雜度都是O(logn)。

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • SpringBoot全局配置long轉(zhuǎn)String丟失精度問(wèn)題解決方案

    SpringBoot全局配置long轉(zhuǎn)String丟失精度問(wèn)題解決方案

    這篇文章主要介紹了SpringBoot全局配置long轉(zhuǎn)String丟失精度問(wèn)題解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-08-08
  • spring?boot自動(dòng)裝配之@ComponentScan注解用法詳解

    spring?boot自動(dòng)裝配之@ComponentScan注解用法詳解

    @ComponentScan的作用就是根據(jù)定義的掃描路徑,把符合掃描規(guī)則的類(lèi)裝配到spring容器中,下面這篇文章主要給大家介紹了關(guān)于spring?boot自動(dòng)裝配之@ComponentScan注解用法的相關(guān)資料,需要的朋友可以參考下
    2023-04-04
  • IKAnalyzer結(jié)合Lucene實(shí)現(xiàn)中文分詞(示例講解)

    IKAnalyzer結(jié)合Lucene實(shí)現(xiàn)中文分詞(示例講解)

    下面小編就為大家?guī)?lái)一篇IKAnalyzer結(jié)合Lucene實(shí)現(xiàn)中文分詞(示例講解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-10-10
  • java字符串遍歷的幾種常用方法總結(jié)

    java字符串遍歷的幾種常用方法總結(jié)

    Java字符串是一系列的Unicode字符序列,但是它卻常常被誤認(rèn)為是char序列,這篇文章主要給大家介紹了關(guān)于java字符串遍歷的幾種常用方法,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-04-04
  • Json傳輸出現(xiàn)中文亂碼問(wèn)題的解決辦法

    Json傳輸出現(xiàn)中文亂碼問(wèn)題的解決辦法

    最近遇到一個(gè)問(wèn)題,就是將中文消息以json格式推給微信服務(wù)器時(shí),收到的消息是亂碼,所以下面這篇文章主要給大家介紹了關(guān)于Json傳輸出現(xiàn)中文亂碼問(wèn)題的解決辦法,需要的朋友可以參考下
    2023-05-05
  • java類(lèi)的定義與使用舉例詳解

    java類(lèi)的定義與使用舉例詳解

    這篇文章主要給大家介紹了關(guān)于java類(lèi)的定義與使用的相關(guān)資料,類(lèi)的方法是用來(lái)定義類(lèi)的行為,在方法中通過(guò)操作類(lèi)的成員變量、編寫(xiě)業(yè)務(wù)邏輯、返回 結(jié)果等實(shí)現(xiàn)類(lèi)的業(yè)務(wù)行為,需要的朋友可以參考下
    2023-11-11
  • Java面試題沖刺第二十六天--實(shí)戰(zhàn)編程

    Java面試題沖刺第二十六天--實(shí)戰(zhàn)編程

    這篇文章主要為大家分享了最有價(jià)值的三道java實(shí)戰(zhàn)面試題,涵蓋內(nèi)容全面,包括數(shù)據(jù)結(jié)構(gòu)和算法相關(guān)的題目、經(jīng)典面試編程題等,感興趣的小伙伴們可以參考一下
    2021-08-08
  • 經(jīng)典的Java面試題及回答集錦(基礎(chǔ)篇)

    經(jīng)典的Java面試題及回答集錦(基礎(chǔ)篇)

    本文給大家收藏整理了java面試題及回答,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧
    2018-03-03
  • Springboot打包部署修改配置文件的方法

    Springboot打包部署修改配置文件的方法

    這篇文章主要介紹了Springboot打包部署修改配置文件的方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-09-09
  • Java詳解線(xiàn)上內(nèi)存暴漲問(wèn)題定位和解決方案

    Java詳解線(xiàn)上內(nèi)存暴漲問(wèn)題定位和解決方案

    本篇文章介紹了我在開(kāi)發(fā)過(guò)程中遇到的線(xiàn)上內(nèi)存暴漲的問(wèn)題,以及定位問(wèn)題原因和解決該問(wèn)題的過(guò)程及思路,通讀本篇對(duì)大家的學(xué)習(xí)或工作具有一定的價(jià)值,需要的朋友可以參考下
    2021-10-10

最新評(píng)論