面试过程中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可否为空?

HashMap可以,为什么呢?

下面是​​HashMap的put​​方法,会发现HashMap调用的是自己内部的hash方法,

​如果key为null则会返回hash值 0​

而value会被存进​​Node​​结点的​​value​​中。不会像HashTable对值进行校验

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);
}

在HashMap中可能会调用​​value.equals​​方法的代码如下,会发现前面做了校验空处理

​value.equals​

HashTable源码解读_空指针异常_02

其它

增删改查元素和HashMap相同。

自行解读或者