java·數據結構·hashMap

特色

  • 線程不安全
  • 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);
}
  • public HashMap()
/**
* 在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
}
  • public HashMap(Map<? extends K, ? extends V> m)
    • 待梳理
    public HashMap(Map<? extends K, ? extends V> m) {
      this.loadFactor = DEFAULT_LOAD_FACTOR;
      putMapEntries(m, false);
    }

小結:

  • java位運算相關知識待概括。 (位運算的目的是提升效率)
    • 1 << k(2^k)
  • double和float區別待概括。
  • HashMap、treemap、treenodes關係
  • 爲何n初始化構造map時,轉換輸入的初始最大容量爲2^k,賦值給threshold做爲實際最大容量。
相關文章
相關標籤/搜索