1、先看結果
Map<String, String> m0 = new HashMap<>(0);// 不創建內部存儲數組
m0.put("k","v");// 內部空間開闢了 1 (數組長度=1)
Map<String, String> m1 = new HashMap<>(1);// 不創建內部存儲數組
m1.put("k","v");// 內部空間開闢了 1 (數組長度=1)
Map<String, String> m2 = new HashMap<>(2);// 不創建內部存儲數組
m2.put("k","v");// 內部空間開闢了 2 (數組長度=2)
Map<String, String> m3 = new HashMap<>(3);// 不創建內部存儲數組
m3.put("k","v");// 內部空間開闢了 4 (數組長度=4)
首先,我們應該知道HashMap內部是用數組存儲數據的。
沒錯,下面這句話,是不創建數組的,所以結論是 0
Map<String, String> m3 = new HashMap<>(3);
2、爲什麼是0?
new HashMap<>(3) 只是設置了threshold(擴容閾值)和loadFactor 加載因子,請看代碼
public HashMap(int initialCapacity, float loadFactor) {
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " +
initialCapacity);
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: " +
loadFactor);
this.loadFactor = loadFactor;
threshold = initialCapacity;
init();
}
3、什麼時候創建數組?
只有調用put的方法的時候才真正的創建數組,具體創建多大的數組呢?從上面的代碼可以看出m3 創建了 長度=4的數組
public V put(K key, V value) {
if (table == EMPTY_TABLE) {
inflateTable(threshold); // 這句話會去創建數組
}
if (key == null)
return putForNullKey(value);
int hash = hash(key);
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
4、數組的長度爲什麼不是3?
k=數組長度-1,因爲要保證k這個值的二進制全是1,所以new HashMap(3),實際數組長度=4,這樣k=3,k的二進制值:11
如果new HashMap(5),內部數組長度=8, k=7,k的二進制:111
private void inflateTable(int toSize) {
// Find a power of 2 >= toSize
int capacity = roundUpToPowerOf2(toSize); // 這句話保證了k(k=數組長度capacity-1)的二進制值全是1
threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);
table = new Entry[capacity];
initHashSeedAsNeeded(capacity);
}
5、分析roundUpToPowerOf2方法 private static int roundUpToPowerOf2(int number) {
// assert number >= 0 : "number must be non-negative";
return number >= MAXIMUM_CAPACITY
? MAXIMUM_CAPACITY
: (number > 1) ? Integer.highestOneBit((number - 1) << 1) : 1;
}
p = number-1 ,然後左移一位p<<1, Integer.highestOneBit(p),獲取最高位,其他位都是0
例子:number=3,p=(二級制0010),p左移一位等於4(二級制0100),然後獲取最高位的結果是4(二級制100)
number=6,p=5(二級制0101),p左移一位等於10(二級制1010),然後獲取最高位的結果是8(二級制1000)
這樣就可以的結果就可以保證k的二級制都是1了
6、爲什麼要保證k的二進制全是1?
static int indexFor(int h, int length) {
// assert Integer.bitCount(length) == 1 : "length must be a non-zero power of 2";
return h & (length-1);
}
因爲要根據hash 值來索引,當前數據存放在哪個下標數組裏,同時還不能越界,如上代碼,把hash和length-1 進行一下與操作,就能找到該數據存放的下標,同時還不越界。
分析的jdk版本jdk7_75
如有不對,請指出!謝謝