一、原因
這個不用多想,肯定是效率問題,那為什麼會造成效率問題呢?
當我們new乙個hashmap沒有對其容量進行初始化的時候,系統會預設建立乙個16大小的集合。當我們使用的集合太小時,就會造成記憶體的浪費,而當hashmap的容量超過臨界值時,hashmap就會擴容到下乙個2的指數冪(2->4,4->8,8->16)。擴容(resize)時,hashmap會重新建立hash表,重新計算沒個元素的位置,這是很消耗資源的。
二、合理的設定
當我們使用hashmap(int initialcapacity)來初始化容量的時候,jdk會預設幫我們計算出乙個相對合理的值當做初始容量。當hashmap的容量值超過了臨界值(threshold)時就會擴容,threshold = hashmap的容量值0.75,比如初始化容量為8的hashmap當大小達到80.75=6時將會擴容到16。當我們設定hashmap的初始化容量是遵循expectedsize(預期大小)/0.75+1,比如expectedsize是6時 6/0.75+1=9,此時jdk處理後會被設定成16,大大降低了hashmap被擴容的機率。
當我們通過hashmap(int initialcapacity)設定初始容量時,hashmap不一定會採取我們設定的初始容量,會根據計算得到乙個新的值(2的指數冪),以保證hash的效率。
ps.為什麼容量一定要是2的指數冪?
簡答:1.節約空間 2.讓元素分布均勻
詳細:hashmap原始碼獲取元素的位置:
static int indexfor(int h, int length)
h:為插入元素的hashcode
length:為map長度
&:與操作
如果length為2的次冪 則length-1 轉化為二進位制必定是11111……的形式,再與h的二進位制與操作效率會非常的快,而且空間不浪費;如果length不是2的次冪,比如length為15,則length-1為14,對應的二進位制為1110,再與h與操作,最後一位都為0,而0001,0011,0101,1001,1011,0111,1101這幾個位置永遠都不能存放元素了,空間浪費相當大,更糟的是這種情況中,陣列可以使用的位置比陣列長度小了很多,這意味著進一步增加了碰撞的機率,減慢了查詢的效率!這樣就會造成空間的浪費。
集合初始化時,指定集合初始值大小。
我們使用的hashmap一般情況的儲存在1w對以上,預設的初始的table容量是16,預設rehash每次容量翻倍,多次重構,影響效能 說明 hashmap 使用 hashmap int initialcapacity 初始化,正例 initialcapacity 需要儲存的元素個數 負載因子 1。...
類初始化時機
虛擬機器規範中並沒有強制約束何時進行載入,但是規範嚴格規定了有且只有下列五種情況必須對類進行初始化 載入 驗證 準備都會隨之發生 以上 5 種場景中的行為稱為對乙個類進行主動引用。除此之外,所有引用類的方式都不會觸發初始化,稱為被動引用。被動引用的常見例子包括 system.out.println ...
類的初始化時機
什麼情況下需要開始類載入過程的第乙個階段 載入 虛擬機器規範中並沒強行約束,這點可以交給虛擬機器的的具體實現自由把握,但是對於初始化階段虛擬機器規範是嚴格規定了如下幾種情況,如果類未初始化會對類進行初始化。建立類的例項 訪問類的靜態變數 除常量 被final修辭的靜態變數 原因 常量一種特殊的變數,...