HashTable 数据结构是一种比较古老的 Dictionary 实现 ,大家常用的hashMap 是实现的AbstractMap。
HashTable 内部使用了Table[] 数组和Entry<K,V> 链表实现。
内部使用了synchronized 关键字保证线程安全,简单粗暴,但是有效。
若担心多线程环境下 hashTable 的阻塞 可以使用 ConcurrentHashMap
简单分析一下hashTable的源码。
public synchronized V put(K key, V value) {
// Make sure the value is not null
//判断value 不为空 否则抛出异常
if (value == null) {
throw new NullPointerException();
}
// Makes sure the key is not already in the hashtable.
// 确保 key 没有保存在 hashTable 中,确定数组下标之后,遍历链表
//比对hash值
Entry<?,?> tab[] = table;
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
@SuppressWarnings("unchecked")
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;
}
}
//若key 不存在hashtable中 新增加一个key
addEntry(hash, key, value, index);
return null;
}
synchronized 修饰 put 方法,使用了泛型;
首先检查value 如果为null 抛出nullpointexception
hashtable key 也不能为空,native的key.hash() 会直接抛出nullPointerException()
接着检查 key 是否已经存在于hashtable 中,通过确认table[] 数据下标之后,遍历 链表
链表遍历
for(; entry != null ; entry = entry.next) {
if ((entry.hash == hash) && entry.key.equals(key)) {
V old = entry.value;
entry.value = value;
return old;
}
}
如果存在则返回 旧值
如果不存在 则
新建一个Entry
private void addEntry(int hash, K key, V value, int index) {
Entry<?,?> tab[] = table;
if (count >= threshold) {
// Rehash the table if the threshold is exceeded
rehash();
tab = table;
hash = key.hashCode();
index = (hash & 0x7FFFFFFF) % tab.length;
}
// Creates the new entry.
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>) tab[index];
tab[index] = new Entry<>(hash, key, value, e);
// 定位到数组下标之后,在链表头部插入一个Entry
count++;
modCount++;
}
//新建一个Entry
protected Entry(int hash, K key, V value, Entry<K,V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
HashTable 数据结构比较老旧,但从HashTable 的源码分析可以更好的掌握 HashMap ConcurrentHashMap