1.继承的父类不同
public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>, Cloneable, Serializable
HashTable继承的是Dictionary类,而HashMap继承的是AbstractMap类
2.扩容机制不同
HashTable初始的容量是11,HashMap是16.他俩的负载因子都是0.75。当需要扩容时,HashTable的容量变为当前值2+1;而HashMap只是当前值2;
HashTable
protected void rehash() {
int var1 = this.table.length;
Hashtable.Entry[] var2 = this.table;
//翻倍+1
int var3 = (var1 << 1) + 1;
if (var3 - 2147483639 > 0) {
if (var1 == 2147483639) {
return;
}
var3 = 2147483639;
}
HashMap
void addEntry(int var1, K var2, V var3, int var4) {
if (this.size >= this.threshold && null != this.table[var4]) {
//翻倍
this.resize(2 * this.table.length);
var1 = null != var2 ? this.hash(var2) : 0;
var4 = indexFor(var1, this.table.length);
}
this.createEntry(var1, var2, var3, var4);
}
3.哈希值和下标计算方式不同
HashTable的哈希值就是利用key值的hashCode()方法获得。然后用哈希值与0X7FFFFFF即二进制为31个1即2147483647进行&操作。(将符号位变成0)。然后用得到的值与数组长度进行取模运算,得到下标。
HashMap是利用自己的哈希算法。先利用hashCode方法获得到哈希值,然后将高位尽量移到地位(JDK1.7),或者将高16位移到低位(JDK1.8),然后进行亦或运算得到最终的哈希值。
HashTable
//计算哈希值
private int hash(Object var1) {
//直接调用hashCode方法
return this.hashSeed ^ var1.hashCode();
}
//计算下标
int var4 = (var3 & 2147483647) % var2.length;
HashMap
final int hash(Object var1) {
int var2 = this.hashSeed;
if (0 != var2 && var1 instanceof String) {
return Hashing.stringHash32((String)var1);
} else {
var2 ^= var1.hashCode();
//将高位尽量移到低位
var2 ^= var2 >>> 20 ^ var2 >>> 12;
return var2 ^ var2 >>> 7 ^ var2 >>> 4;
}
}
//获取下标(哈希值与数组长度-1进行&运算)
static int indexFor(int var0, int var1) {
return var0 & var1 - 1;
4.HashTable的Key-Value都不能为null
会抛出空指针异常
5.线程安全
HashTable是线程安全的。因为HashTable给那些可能产生多线程线程并发错误的方法,加上了synchronized。但是这样效率会大大降低
6.遍历方式不同
HashTable用的是Enumeration。HashMap是迭代器