天天看點

HashTable源碼解讀

面試過程中HashTable是一個常考的知識點

常常會将HashMap 或 ConcurrentHashMap進行比較。

今天特意看了一下 HashTable源碼

總結了幾個常考知識點

一、初始容量11,最大容量為 231-8

HashMap和ConcurrentHashMap預設初始容量是16。而HashTable是11

預設的擴容因子都是

0.75

,也都是2倍的方式進行擴容

下面是它的構造方法如下

// 最大容量
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
// 預設空參構造,建立時初始容量是11,而HashMap和ConcurrentHashMap預設初始容量是16
public Hashtable() {
    this(11, 0.75f);
}

public Hashtable(int initialCapacity, float loadFactor) {
    if (initialCapacity < 0)
        throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
    if (loadFactor <= 0 || Float.isNaN(loadFactor))
        throw new IllegalArgumentException("Illegal Load: "+loadFactor);
    if (initialCapacity==0)
        initialCapacity = 1;
    this.loadFactor = loadFactor;
    table = new Entry<?,?>[initialCapacity];
    threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
}

public Hashtable(int initialCapacity) {
    this(initialCapacity, 0.75f);
}

public Hashtable(Map<? extends K, ? extends V> t) {
    this(Math.max(2*t.size(), 11), 0.75f);
    putAll(t);
}
           

二、線程安全問題

HashTable和ConcurrentHashMap都是線程安全的,而HashMap是線程不安全的

原因在于HashTable的增删改查都加了

synchronized

會看下下面一排的

synchronized

關鍵字

HashTable源碼解讀

三、為什麼說HashTable的key和value都不能為null

貼出源碼,很容易就明白了,已

put

方法為例

會發現

value==null

時就會抛出一個空指針異常

key=null

呢?會發現

int hash = key.hashCode()

很明顯如果key為null也會抛一個空指針異常。

故HashTable的Key和value都不可以為null

public synchronized V put(K key, V value) {
    if (value == null) {
        throw new NullPointerException();
    }
    Entry<?,?> tab[] = table;
    int hash = key.hashCode();
    int index = (hash & 0x7FFFFFFF) % tab.length;
    Entry<K,V> entry = (Entry<K,V>)tab[index];
    for(; entry != null ; entry = entry.next) {
        if ((entry.hash == hash) && entry.key.equals(key)) {
            V old = entry.value;
            entry.value = value;
            return old;
        }
    }
    addEntry(hash, key, value, index);
    return null;
}
           
擴充:HashMap的key和value可否為空?
public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
}
static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
           

其它