HashMap负载因子
下面是HashMap的一個(gè)構(gòu)造函數(shù),兩個(gè)參數(shù)initialCapacity,loadFactor
這關(guān)系HashMap的迭代性能。
1 /** 2 * Constructs an empty <tt>HashMap</tt> with the specified initial 3 * capacity and load factor. 4 * 5 * @param initialCapacity the initial capacity 6 * @param loadFactor the load factor 7 * @throws IllegalArgumentException if the initial capacity is negative 8 * or the load factor is nonpositive 9 */ 10 public HashMap(int initialCapacity, float loadFactor) { 11 if (initialCapacity < 0) 12 throw new IllegalArgumentException("Illegal initial capacity: " + 13 initialCapacity); 14 if (initialCapacity > MAXIMUM_CAPACITY) 15 initialCapacity = MAXIMUM_CAPACITY; 16 if (loadFactor <= 0 || Float.isNaN(loadFactor)) 17 throw new IllegalArgumentException("Illegal load factor: " + 18 loadFactor); 19 this.loadFactor = loadFactor; 20 this.threshold = tableSizeFor(initialCapacity); 21 }關(guān)于這兩個(gè)參數(shù)值的設(shè)定界限:
1. initialCapacity是map的初始化容量,initialCapacity > MAXIMUM_CAPACITY,表明map的最大容量是1<<30,也就是1左移30位,每左移一位乘以2,所以就是1*2^30=1073741824.
2. loadFactor是map的負(fù)載因子,loadFactor <= 0 || Float.isNaN(loadFactor),表明負(fù)載因子要大于0,且是非無(wú)窮大的數(shù)字
?
負(fù)載因子為什么會(huì)影響HashMap性能
首先回憶HashMap的數(shù)據(jù)結(jié)構(gòu),
我們都知道有序數(shù)組存儲(chǔ)數(shù)據(jù),對(duì)數(shù)據(jù)的索引效率都很高,但是插入和刪除就會(huì)有性能瓶頸(回憶ArrayList),
鏈表存儲(chǔ)數(shù)據(jù),要一次比較元素來(lái)檢索出數(shù)據(jù),所以索引效率低,但是插入和刪除效率高(回憶LinkedList),
兩者取長(zhǎng)補(bǔ)短就產(chǎn)生了哈希散列這種存儲(chǔ)方式,也就是HashMap的存儲(chǔ)邏輯.
而負(fù)載因子表示一個(gè)散列表的空間的使用程度,有這樣一個(gè)公式:initailCapacity*loadFactor=HashMap的容量。
所以負(fù)載因子越大則散列表的裝填程度越高,也就是能容納更多的元素,元素多了,鏈表大了,所以此時(shí)索引效率就會(huì)降低。
反之,負(fù)載因子越小則鏈表中的數(shù)據(jù)量就越稀疏,此時(shí)會(huì)對(duì)空間造成爛費(fèi),但是此時(shí)索引效率高。
?
如何科學(xué)設(shè)置 initailCapacity,loadFactor的值
HashMap有三個(gè)構(gòu)造函數(shù),可以選用無(wú)參構(gòu)造函數(shù),不進(jìn)行設(shè)置。默認(rèn)值分別是16和0.75.
官方的建議是initailCapacity設(shè)置成2的n次冪,laodFactor根據(jù)業(yè)務(wù)需求,如果迭代性能不是很重要,可以設(shè)置大一下。
?
為什么initailCapacity要設(shè)置成2的n次冪,網(wǎng)友解釋了,我覺(jué)得很對(duì),以下摘自網(wǎng)友博客:深入理解HashMap
左邊兩組是數(shù)組長(zhǎng)度為16(2的4次方),右邊兩組是數(shù)組長(zhǎng)度為15。兩組的hashcode均為8和9,但是很明顯,當(dāng)它們和1110“與”的時(shí)候,產(chǎn)生了相同的結(jié)果,也就是說(shuō)它們會(huì)定
位到數(shù)組中的同一個(gè)位置上去,這就產(chǎn)生了碰撞,8和9會(huì)被放到同一個(gè)鏈表上,那么查詢的時(shí)候就需要遍歷這個(gè)鏈表,得到8或者9,這樣就降低了查詢的效率。同時(shí),我們也可以
發(fā)現(xiàn),當(dāng)數(shù)組長(zhǎng)度為15的時(shí)候,hashcode的值會(huì)與14(1110)進(jìn)行“與”,那么最后一位永遠(yuǎn)是0,而0001,0011,0101,1001,1011,0111,1101這幾個(gè)位置永遠(yuǎn)都不能
存放元素了,空間浪費(fèi)相當(dāng)大,更糟的是這種情況中,數(shù)組可以使用的位置比數(shù)組長(zhǎng)度小了很多,這意味著進(jìn)一步增加了碰撞的幾率,減慢了查詢的效率!
?所以說(shuō),當(dāng)數(shù)組長(zhǎng)度為2的n次冪的時(shí)候,不同的key算得得index相同的幾率較小,那么數(shù)據(jù)在數(shù)組上分布就比較均勻,也就是說(shuō)碰撞的幾率小,相對(duì)的,查詢的時(shí)候就不用
遍歷某個(gè)位置上的鏈表,這樣查詢效率也就較高了。
?
resize()方法
?initailCapacity,loadFactor會(huì)影響到HashMap擴(kuò)容。
HashMap每次put操作是都會(huì)檢查一遍 size(當(dāng)前容量)>initailCapacity*loadFactor 是否成立。如果不成立則HashMap擴(kuò)容為以前的兩倍(數(shù)組擴(kuò)成兩倍),
然后重新計(jì)算每個(gè)元素在數(shù)組中的位置,然后再進(jìn)行存儲(chǔ)。這是一個(gè)十分消耗性能的操作。
所以如果能根據(jù)業(yè)務(wù)預(yù)估出HashMap的容量,應(yīng)該在創(chuàng)建的時(shí)候指定容量,那么可以避免resize().
?
轉(zhuǎn)載于:https://www.cnblogs.com/yesiamhere/p/6653135.html
總結(jié)
以上是生活随笔為你收集整理的HashMap负载因子的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 文件搜索命令
- 下一篇: 屏幕录制工具(可录制GIF)