浅析JDK1.8 Hashtable源码。
写在开篇
简单介绍一下Hashtable:
- 和HashMap一样,Hashtable 也是一个散列表,它存储的内容是键值对(key-value)映射
- Hashtable是线程安全的,HashMap是非线程安全的
- Hashtable的key、value都不可以为null
类的继承关系
Hashtable继承于Dictionary,实现了Map(规定了Map的操作规范)、Cloneable(可拷贝)、java.io.Serializable(可序列化)这几个接口。1
2
3public class Hashtable<K,V>
    extends Dictionary<K,V>
    implements Map<K,V>, Cloneable, java.io.Serializable {
存储结点–Entry
| 1 | private static class Entry<K,V> implements Map.Entry<K,V> { | 
成员变量
| 1 | /** | 
构造方法
| 1 | /** | 
可以看到:
- HashMap对底层数组采取的懒加载,即当执行第一次插入时才会创建数组,而Hashtable在初始化时就创建了数组
- HashMap中数组的默认初始容量是16,并且必须的是2的指数倍数,而Hashtable中默认的初始容量是11,并且不要求必须是2的指数倍数。
Map接口的实现
put()
| 1 | public synchronized V put(K key, V value) { | 
接着看下addEntry()1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18private void addEntry(int hash, K key, V value, int index) {
       modCount++;
       Entry<?,?> tab[] = table;
       if (count >= threshold) {
           // 扩容
           rehash();
           tab = table; // 更新tab
           hash = key.hashCode(); // 更新hash
           index = (hash & 0x7FFFFFFF) % tab.length; // 更新下标
       }
       // 头插法插入新元素
       Entry<K,V> e = (Entry<K,V>) tab[index];
       tab[index] = new Entry<>(hash, key, value, e);
       count++;
   }
再看看rehash():1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29protected void rehash() {
       int oldCapacity = table.length;
       Entry<?,?>[] oldMap = table;
       // 扩容操作
       int newCapacity = (oldCapacity << 1) + 1;
       if (newCapacity - MAX_ARRAY_SIZE > 0) {
           if (oldCapacity == MAX_ARRAY_SIZE)
               return;
           newCapacity = MAX_ARRAY_SIZE;
       }
       Entry<?,?>[] newMap = new Entry<?,?>[newCapacity];
       modCount++;
       threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
       table = newMap;
	// 采用头插法将原数组元素复制到新数组
       for (int i = oldCapacity ; i-- > 0 ;) {
           for (Entry<K,V> old = (Entry<K,V>)oldMap[i] ; old != null ; ) {
               Entry<K,V> e = old;
               old = old.next;
               int index = (e.hash & 0x7FFFFFFF) % newCapacity;
               e.next = (Entry<K,V>)newMap[index];
               newMap[index] = e;
           }
       }
   }
get()
| 1 | public synchronized V get(Object key) { | 
remove()
remove()先查询键值相同的元素,如果存在则删除结点,同时modCount++,count–。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22public synchronized V remove(Object key) {
       Entry<?,?> tab[] = table;
       int hash = key.hashCode();
       int index = (hash & 0x7FFFFFFF) % tab.length;
       
       Entry<K,V> e = (Entry<K,V>)tab[index];
       for(Entry<K,V> prev = null ; e != null ; prev = e, e = e.next) {
           if ((e.hash == hash) && e.key.equals(key)) {
               modCount++;
               if (prev != null) {
                   prev.next = e.next;
               } else {
                   tab[index] = e.next;
               }
               count--;
               V oldValue = e.value;
               e.value = null;
               return oldValue;
           }
       }
       return null;
   }
