特色
- 線程不安全
- HashMap、和Hashtable、SynchronizedMap區別:
- HashMap 線程不安全,能夠有null的key值或value值。
- hashtable 線程安全,不能有null的key值或value值。
- ConcurrentHashMap 線程安全,不能有null的key值或value值。刪除操做比較費時。
- SynchronizedMap 線程安全,能夠有null的key值或value值。
- 能夠經過
Collections.synchronizedMap(new HashMap<String, Object>())
方式建立
- 性能:HashMap>ConcurrentHashMap>SynchronizedMap>Hashtable
構造方法
相關參數
- initialCapacity:初始最大容量,默認1<<4(2^4),內部實際使用的變量是threshold(默認容量) ,實際最大容量並無存放。
- loadFactor:加載因子(默認容量=初始最大容量*加載因子),默認0.75
- threshold:默認容量,內部變量,根據initialCapacity生成。執行構造方法時,將輸入的initialCapacity轉爲不小於當前數的最小的2^k的值,做爲threshold。在第一次構建table時(第一次put,執行resize()方法),table的大小設置爲threshold,而後讓threshold = thresholdloadFactor;後續每一次resize,都是table的大小 = table的大小 2;threshold = threshold * 2;
- 默認關係:threshold = initialCapacity * loadFactor(達到最大容量時不知足該等式)
平衡與折衷
- 加載因子:hash表中元素的填滿程度,加載因子越大,空間利用率越高,衝突機會越高(查詢成本越高)
代碼解析
- public HashMap(int initialCapacity, float loadFactor)
public HashMap(int initialCapacity, float loadFactor) {
/**初始最大容量爲非負整數*/
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " +
initialCapacity);
/**
* static final int MAXIMUM_CAPACITY = 1 << 30;
* 當 initialCapacity 大於最大容量(2^30,約10.74億)時,強制設置爲容量爲最大容量。
*/
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
/**
* 加載因子爲大於0的浮點數
* public static boolean isNaN(float v) {
* return (v != v);
* }
* Float.isNaN(loadFactor):NaN(not-a-number),例如. float v = 0.0f/0.0f;
*/
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: " +
loadFactor);
/**賦值容量因子*/
this.loadFactor = loadFactor;
/**
* 轉換輸入的初始最大容量爲2^k,賦值給threshold做爲實際最大容量
* 這樣作的意義待分析
*/
this.threshold = tableSizeFor(initialCapacity);
}
/**
* 獲取不小於當前數的最小的2^k的值.
* 例如:31->32,65->128
*/
static final int tableSizeFor(int cap) {
int n = cap - 1;
n |= n >>> 1;
n |= n >>> 2;
n |= n >>> 4;
n |= n >>> 8;
n |= n >>> 16;
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}
- public HashMap(int initialCapacity)
public HashMap(int initialCapacity) {
this(initialCapacity, DEFAULT_LOAD_FACTOR);
}
/**
* 在resize()方法中設置threshold的值
* newCap = DEFAULT_INITIAL_CAPACITY;
* newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
*/
public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
}
小結:
- java位運算相關知識待概括。 (位運算的目的是提升效率)
- double和float區別待概括。
- HashMap、treemap、treenodes關係
- 爲何n初始化構造map時,轉換輸入的初始最大容量爲2^k,賦值給threshold做爲實際最大容量。