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,替换对应的valuefor(; 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;
在此处做&操作的目的是获取到正整数。
