我們日常經常定義hashMap,是這樣的:
Map<String,String> map = new HashMap<>();
可是就是這樣一句簡單的代碼,都可以優化,那就是給map設置初始容量大小。比如:
Map<String,String> map = new HashMap<>(4);
當用代碼檢查工具掃描時,也會提醒你設置初始容量
一、如果不設置初始大小,那默認大小是多大?
1、如果不設置初始容量,那么構造方法是這樣的:
即,所有Map相關屬性全部用默認值
2、當put第一個元素時,因為map的Node<K,V>[] table為空,所以需要resize()
3、接下來走resize方法,因為其他屬性都為默認值,所以容量大小會設置為:DEFAULT_INITIAL_CAPACITY
我們可以看到這個值默認為16
所以,這時的map的node數組,是一個容量為16的數組。
二、如何擴容的
1、看一下put方法
當元素個數>threshold時,會觸發擴容。
擴多大呢?代碼會走到這里:
即:擴容到原容量的2倍。
回答標題的問題:為什么要設置初始容量?
1、如果你的map只需要put幾個元素,那么這樣就會造成容量的浪費。
2、如果你的map需要put成百上千個元素,那么這個map就會不斷擴容(從16、32、64、128...),擴容需要創建新數組,並且rehash等操作,這樣會導致一些性能的浪費。
所以,如果在寫代碼時,如果能夠預估map的容量,就可以盡量去設置他的容量大小,這樣可以減少容量浪費和減少擴容次數。
3、初始容量設置為多大?
通過上面的內容可以看到,當元素個數超過總容量的0.75倍時,會觸發擴容,此時容量為此前的2倍。
通過測試,也證實了如上的說法:
當元素為1時,擴容大小為2。
當元素為2時,擴容大小為4。
當元素為3時,擴容大小為4。
當元素為4時,擴容大小為8。
當元素為5時,擴容大小為8。
當元素為6時,擴容大小為8。
當元素為7時,擴容大小為16。(7 > 8 * 0.75)
。。。
所以如何設置一個初始容量,從而減小擴容次數呢?
設置容量的大小應該是:
1、預估元素個數,m(比如:5)
2、取離m最近的2的n次方的值:x(比如:8)。
3、如果大於 m>0.75x,則x=x*2