面试过程中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可否为空?
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
其它
增删改查元素和HashMap相同。
自行解读或者