HashTable特性
- HashTable是线程安全的集合,通过synchronized关键字实现;
- HashTable的key和value均不允许为null,使用会产生空指针问题;
HashTable源码分析
- table是一个数组,表示哈希桶;
- count表示存储的元素个数;
- loadFactor表示负载因子,默认值是0.75,这是时间和空间权衡后的最优值;
- threshold表示元素存储的阈值,容量*负载因子可以得到该值;
HashTable初始化
/**
* Constructs a new, empty hashtable with the specified initial
* capacity and the specified load factor.
*
* @param initialCapacity the initial capacity of the hashtable.
* @param loadFactor the load factor of the hashtable.
* @throws IllegalArgumentException if the initial capacity is less
* than zero, or if the load factor is nonpositive.
*/
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);
}
put操作
/**
* Maps the specified {@code key} to the specified
* {@code value} in this hashtable. Neither the key nor the
* value can be {@code null}. <p>
*
* The value can be retrieved by calling the {@code get} method
* with a key that is equal to the original key.
*
* @param key the hashtable key
* @param value the value
* @return the previous value of the specified key in this hashtable,
* or {@code null} if it did not have one
* @throws NullPointerException if the key or value is
* {@code null}
* @see Object#equals(Object)
* @see #get(Object)
*/
public synchronized V put(K key, V value) {
// HashTable的key和value都不允许为null,否则会产生空指针
if (value == null) {
throw new NullPointerException();
}
// Makes sure the key is not already in the hashtable.
Entry<?,?> tab[] = table;
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
@SuppressWarnings("unchecked")
Entry<K,V> entry = (Entry<K,V>)tab[index];
//如果有相同的entry,替换对应的value
for(; entry != null ; entry = entry.next) {
if ((entry.hash == hash) && entry.key.equals(key)) {
V old = entry.value;
entry.value = value;
return old;
}
}
//如果没有对应的entry,新增一个Entry,链表的插入使用头插法
addEntry(hash, key, value, index);
return null;
}
HashTable计算桶位置的公式:
int index = (hash & 0x7FFFFFFF) % tab.length;
在此处做&操作的目的是获取到正整数。