面試過程中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的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);
}