HashMap是Hashtable的非线程安全版。非常明显由源码可以看出,Hashtable与HashMap并不出于同一个人之手,代码风格有很大差别。
首先,Hashtable继承自Dictionary接口而不是Map接口,为什么呢?Dictionary接口其实与Map接口差不多,但是已经被废弃,被Map接口所取代。与HashMap相同,Hashtable也实现了java.lang.Cloneable接口与java.io.Serializable接口。
数据结构上,Hashtable与HashMap的结构是几乎一样的实现。
那么Hashtable在源码大体结构与HashMap相似的情况下,有哪些区别呢?首先,Hashtable是线程安全的,其大多数方法是synchronized()的,当然构造方法除外(构造器不能用abstract,final,static,synchronized及native来修饰只能是public ,protected,private)。
其次,Hashtable的初始默认桶容量为11,默认装载因子为0.75,而HashMap则是16和0.75。
然后,Hashtable的索引计算方法与HashMap完全不同,实际上,HashMap会使用一个非常好用的哈希函数来对键的hashCode做哈希,然后将其映射到Entry数组的对应位置,而Hashtable则将键值的hashCode直接与0x7fffffff直接相与,然后模数组的长度,这里就可以看出,由于Hashtable是早期版本,因此,并没有想出像HashMap那样,使用桶容量必须是2的幂次以及相应的求数组索引的方法的一系列优化措施,因此,这里的模运算不能不说是一个非常耗时的操作,相比HashMap的实现,就没有那么精妙。
public synchronized boolean containsKey(Object key) {
Entry tab[] = table;
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
if ((e.hash == hash) && e.key.equals(key)) {
return true;
}
}
return false; protected void rehash() {
int oldCapacity = table.length;
Entry[] oldMap = table;
int newCapacity = oldCapacity * 2 + 1;
Entry[] newMap = new Entry[newCapacity];
modCount++;
threshold = (int)(newCapacity * loadFactor);
table = newMap;
for (int i = oldCapacity ; i-- > 0 ;) {
for (Entry<K,V> old = oldMap[i] ; old != null ; ) {
Entry<K,V> e = old;
old = old.next;
int index = (e.hash & 0x7FFFFFFF) % newCapacity;
e.next = newMap[index];
newMap[index] = e;
}
}
}
关于Hashtable,还有一点,Hashtable实现了map自己的hashCode。这个函数应该是神来之笔,因为其实现是很巧妙的。
public synchronized int hashCode() {
/*
* This code detects the recursion caused by computing the hash code
* of a self-referential hash table and prevents the stack overflow
* that would otherwise result. This allows certain 1.1-era
* applets with self-referential hash tables to work. This code
* abuses the loadFactor field to do double-duty as a hashCode
* in progress flag, so as not to worsen the space performance.
* A negative load factor indicates that hash code computation is
* in progress.
*/
int h = 0;
if (count == 0 || loadFactor < 0)
return h; // Returns zero
loadFactor = -loadFactor; // Mark hashCode computation in progress
Entry[] tab = table;
for (int i = 0; i < tab.length; i++)
for (Entry e = tab[i]; e != null; e = e.next)
h += e.key.hashCode() ^ e.value.hashCode();
loadFactor = -loadFactor; // Mark hashCode computation complete
return h;
}另,HashMap中并没有看到对于hashCode的实现。
原文:http://blog.csdn.net/wangqisen/article/details/18220881