成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

HashMap中傻傻分不清楚的那些概念

開發 開發工具
很多人在通過閱讀源碼的方式學習Java,這是個很好的方式。而JDK的源碼自然是首選。在JDK的眾多類中,我覺得HashMap及其相關的類是設計的比較好的。很多人讀過HashMap的代碼,不知道你們有沒有和我一樣,覺得HashMap中關于容量相關的參數定義的太多了,傻傻分不清楚。

很多人在通過閱讀源碼的方式學習Java,這是個很好的方式。而JDK的源碼自然是***。在JDK的眾多類中,我覺得HashMap及其相關的類是設計的比較好的。很多人讀過HashMap的代碼,不知道你們有沒有和我一樣,覺得HashMap中關于容量相關的參數定義的太多了,傻傻分不清楚。

[[230071]]

其實,這篇文章介紹的內容比較簡單,只要認真的看看HashMap的原理還是可以理解的,單獨寫一篇文章的原因是因為我后面還有幾篇關于HashMap源碼分析的文章,這些概念不熟悉的話閱讀后面的文章會很吃力。

HashMap中重要的成員變量

先來看一下,HashMap中都定義了哪些成員變量。

上面是一張HashMap中主要的成員變量的圖,其中有一個是我們本文主要關注的: size、loadFactor、threshold、DEFAULT_LOAD_FACTOR和DEFAULT_INITIAL_CAPACITY。

我們先來簡單解釋一下這些參數的含義,然后再分析他們的作用。

HashMap類中有以下主要成員變量:

  • transient int size; 

記錄了Map中KV對的個數

  • loadFactor 

裝載印子,用來衡量HashMap滿的程度。loadFactor的默認值為0.75f(static final float DEFAULT_LOAD_FACTOR = 0.75f;)。

  • int threshold; 

臨界值,當實際KV個數超過threshold時,HashMap會將容量擴容,threshold=容量*加載因子

  • 除了以上這些重要成員變量外,HashMap中還有一個和他們緊密相關的概念:capacity 

容量,如果不指定,默認容量是16(static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;)

可能看完了你還是有點蒙,size和capacity之間有啥關系?為啥要定義這兩個變量。loadFactor和threshold又是干啥的?

size 和 capacity

HashMap中的size和capacity之間的區別其實解釋起來也挺簡單的。我們知道,HashMap就像一個“桶”,那么capacity就是這個桶“當前”最多可以裝多少元素,而size表示這個桶已經裝了多少元素。來看下以下代碼:

  1. Map<String, String> map = new HashMap<String, String>(); 
  2. map.put("hollis""hollischuang"); 
  3.  
  4. Class<?> mapType = map.getClass(); 
  5. Method capacity = mapType.getDeclaredMethod("capacity"); 
  6. capacity.setAccessible(true); 
  7. System.out.println("capacity : " + capacity.invoke(map)); 
  8.  
  9. Field size = mapType.getDeclaredField("size"); 
  10. size.setAccessible(true); 
  11. System.out.println("size : " + size.get(map)); 

我們定義了一個新的HashMap,并想其中put了一個元素,然后通過反射的方式打印capacity和size。輸出結果為:capacity : 16、size : 1

默認情況下,一個HashMap的容量(capacity)是16,設計成16的好處我在《全網把Map中的hash()分析的最透徹的文章,別無二家。》中也簡單介紹過,主要是可以使用按位與替代取模來提升hash的效率。

為什么我剛剛說capacity就是這個桶“當前”最多可以裝多少元素呢?當前怎么理解呢。其實,HashMap是具有擴容機制的。在一個HashMap***次初始化的時候,默認情況下他的容量是16,當達到擴容條件的時候,就需要進行擴容了,會從16擴容成32。

我們知道,HashMap的重載的構造函數中,有一個是支持傳入initialCapacity的,那么我們嘗試著設置一下,看結果如何。

  1. Map<String, String> map = new HashMap<String, String>(1); 
  2. map.put("hahaha""hollischuang"); 
  3.  
  4. Class<?> mapType = map.getClass(); 
  5. Method capacity = mapType.getDeclaredMethod("capacity"); 
  6. capacity.setAccessible(true); 
  7. System.out.println("capacity : " + capacity.invoke(map)); 
  8.  
  9. Map<String, String> map = new HashMap<String, String>(7); 
  10. map.put("hahaha""hollischuang"); 
  11.  
  12. Class<?> mapType = map.getClass(); 
  13. Method capacity = mapType.getDeclaredMethod("capacity"); 
  14. capacity.setAccessible(true); 
  15. System.out.println("capacity : " + capacity.invoke(map)); 
  16.  
  17.  
  18. Map<String, String> map = new HashMap<String, String>(9); 
  19. map.put("hahaha""hollischuang"); 
  20.  
  21. Class<?> mapType = map.getClass(); 
  22. Method capacity = mapType.getDeclaredMethod("capacity"); 
  23. capacity.setAccessible(true); 
  24. System.out.println("capacity : " + capacity.invoke(map)); 

分別執行以上3段代碼,分別輸出:capacity : 2、capacity : 8、capacity : 16。

也就是說,默認情況下HashMap的容量是16,但是,如果用戶通過構造函數指定了一個數字作為容量,那么Hash會選擇大于該數字的***個2的冪作為容量。(1->2、7->8、9->16)

這里有一個小建議:在初始化HashMap的時候,應該盡量指定其大小。尤其是當你已知map中存放的元素個數時。(《阿里巴巴Java開發規約》)

loadFactor 和 threshold

前面我們提到過,HashMap有擴容機制,就是當達到擴容條件時會進行擴容,從16擴容到32、64、128...

那么,這個擴容條件指的是什么呢?

其實,HashMap的擴容條件就是當HashMap中的元素個數(size)超過臨界值(threshold)時就會自動擴容。

在HashMap中,threshold = loadFactor * capacity。

loadFactor是裝載因子,表示HashMap滿的程度,默認值為0.75f,設置成0.75有一個好處,那就是0.75正好是3/4,而capacity又是2的冪。所以,兩個數的乘積都是整數(capacity為2也同樣)。

對于一個默認的HashMap來說,默認情況下,當其size大于12(16*0.75)時就會觸發擴容。

驗證代碼如下:

  1. Map<String, String> map = new HashMap<>(); 
  2. map.put("hollis1""hollischuang"); 
  3. map.put("hollis2""hollischuang"); 
  4. map.put("hollis3""hollischuang"); 
  5. map.put("hollis4""hollischuang"); 
  6. map.put("hollis5""hollischuang"); 
  7. map.put("hollis6""hollischuang"); 
  8. map.put("hollis7""hollischuang"); 
  9. map.put("hollis8""hollischuang"); 
  10. map.put("hollis9""hollischuang"); 
  11. map.put("hollis10""hollischuang"); 
  12. map.put("hollis11""hollischuang"); 
  13. map.put("hollis12""hollischuang"); 
  14. Class<?> mapType = map.getClass(); 
  15.  
  16. Method capacity = mapType.getDeclaredMethod("capacity"); 
  17. capacity.setAccessible(true); 
  18. System.out.println("capacity : " + capacity.invoke(map)); 
  19.  
  20. Field size = mapType.getDeclaredField("size"); 
  21. size.setAccessible(true); 
  22. System.out.println("size : " + size.get(map)); 
  23.  
  24. Field threshold = mapType.getDeclaredField("threshold"); 
  25. threshold.setAccessible(true); 
  26. System.out.println("threshold : " + threshold.get(map)); 
  27.  
  28. Field loadFactor = mapType.getDeclaredField("loadFactor"); 
  29. loadFactor.setAccessible(true); 
  30. System.out.println("loadFactor : " + loadFactor.get(map)); 
  31.  
  32. map.put("hollis13""hollischuang"); 
  33. Method capacity = mapType.getDeclaredMethod("capacity"); 
  34. capacity.setAccessible(true); 
  35. System.out.println("capacity : " + capacity.invoke(map)); 
  36.  
  37. Field size = mapType.getDeclaredField("size"); 
  38. size.setAccessible(true); 
  39. System.out.println("size : " + size.get(map)); 
  40.  
  41. Field threshold = mapType.getDeclaredField("threshold"); 
  42. threshold.setAccessible(true); 
  43. System.out.println("threshold : " + threshold.get(map)); 
  44.  
  45. Field loadFactor = mapType.getDeclaredField("loadFactor"); 
  46. loadFactor.setAccessible(true); 
  47. System.out.println("loadFactor : " + loadFactor.get(map)); 

輸出結果:

  1. capacity : 16 
  2. size : 12 
  3. threshold : 12 
  4. loadFactor : 0.75 
  5.  
  6. capacity : 32 
  7. size : 13 
  8. threshold : 24 
  9. loadFactor : 0.75 

當HashMap中的元素個數達到13的時候,capacity就從16擴容到32了。

HashMap中還提供了一個支持傳入initialCapacity,loadFactor兩個參數的方法,來初始化容量和裝載因子。不過,一般不建議修改loadFactor的值。

總結

HashMap中size表示當前共有多少個KV對,capacity表示當前HashMap的容量是多少,默認值是16,每次擴容都是成倍的。loadFactor是裝載因子,當Map中元素個數超過loadFactor* capacity的值時,會觸發擴容。loadFactor* capacity可以用threshold表示。

【本文是51CTO專欄作者Hollis的原創文章,作者微信公眾號Hollis(ID:hollischuang)】

戳這里,看該作者更多好文

責任編輯:武曉燕 來源: 51CTO專欄
相關推薦

2021-03-10 08:56:37

Zookeeper

2024-02-29 09:08:56

Encoding算法加密

2021-07-27 07:31:16

JavaArrayList數組

2022-05-15 21:52:04

typeTypeScriptinterface

2018-12-17 12:30:05

Kubernetes存儲存儲卷

2021-02-14 22:33:23

Java字符字段

2020-10-30 08:20:04

SD卡TF卡存儲

2023-09-03 21:18:07

Python編程語言

2021-11-09 06:01:35

前端JITAOT

2020-03-03 17:35:09

Full GCMinor

2023-02-27 15:46:19

數據元元數據

2016-11-04 12:51:46

Unix網絡IO 模型

2024-11-04 00:00:03

viewportDOMSPA

2022-02-25 09:14:33

類變量共享實例變量

2021-02-08 23:47:51

文件存儲塊存儲對象存儲

2025-05-12 08:40:00

前端監控DOM

2020-11-11 07:32:18

MySQL InnoDB 存儲

2023-04-11 15:57:49

JavaScriptCSSHTML

2021-01-13 08:10:26

接口IEnumeratorIEnumerable

2019-11-21 14:22:12

WiFiWLAN區別
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 中文字幕精品一区二区三区精品 | 国产 91 视频| 天天干夜夜操视频 | 亚洲成人一区二区在线 | 亚洲激情av | 超碰免费在线 | 久久精品一 | 国产精品区二区三区日本 | 国产精品免费观看视频 | 亚洲91| 国产精品久久久久aaaa樱花 | 99精品欧美一区二区三区 | 日本精品视频 | 亚洲欧美在线观看 | 最新中文字幕一区 | 午夜影院操 | 国产精久久久 | 亚洲国产精品一区二区三区 | 久久综合av | 毛色毛片免费看 | 精品视频一区二区 | 欧美日韩国产精品一区 | 国产一二三区免费视频 | 日韩免费视频 | 欧美视频福利 | 国产一区二区视频在线 | 欧美日韩网站 | 毛片网站在线观看视频 | 精品国产久 | 国产精品美女一区二区 | 色姑娘综合网 | 午夜影院中文字幕 | 在线免费观看黄色网址 | 久久久久无码国产精品一区 | 波多野结衣一区二区三区在线观看 | 久久黄色精品视频 | 中文字幕欧美日韩一区 | 国产视频一区二区三区四区五区 | 一区二区三区中文字幕 | 欧美不卡在线 | 免费成人高清 |