1: 父类不一样
- Hashtable
class Hashtable<K,V> extends Dictionary<K,V>
- HashMap
HashMap<K, V> extends AbstractMap<K, V>
2: Capacity 不一样
- Hashtable
this(11, 0.75f);
- HashMap
HashMap(16, 0.75f);
3:线程安全不一样
- HashMap : 无锁
- Hashtable : 好多锁
4:null值
- HashMap : null可以作为键(放在 hash 桶的第 0 个位置)
- HashTable: key和value都不允许出现null值,否则会抛出NullPointerException异常
5:遍历方式:
- HashMap : Iterator
- HashTable: Enumeration** (/i,nju:mə'reiʃən/ : 计数;列举)**
6: 哈希值的使用不同
- HashMap : 有自己的 hash 函数,重新计算自己的 Hash 值
- HashTable: 直接使用对象的hashCode
- ps:以下就是 hashMap 计算hash 的方式
/**
* 这个扰动函数,
* Computes key.hashCode() and spreads (XORs) higher bits of hash
* to lower. Because the table uses power-of-two masking, sets of
* hashes that vary only in bits above the current mask will
* always collide. (Among known examples are sets of Float keys
* holding consecutive whole numbers in small tables.) So we
* apply a transform that spreads the impact of higher bits
* downward. There is a tradeoff between speed, utility, and
* quality of bit-spreading. Because many common sets of hashes
* are already reasonably distributed (so don't benefit from
* spreading), and because we use trees to handle large sets of
* collisions in bins, we just XOR some shifted bits in the
* cheapest possible way to reduce systematic lossage, as well as
* to incorporate impact of the highest bits that would otherwise
* never be used in index calculations because of table bounds.
*
* 作用: 在 table 的 size 还是很大的情况下,让 key 的高 16 位,也参与路由寻址;
*/
static final int hash(Object key) {
int h;
// key 是空的,直接放在 0 的位置;
/*
* h = 0b 0010 0101 1010 1100 0011 1111 0010 1110
* 0b 0010 0101 1010 1100 0011 1111 0010 1110 >>>16 = 0b 0000 0000 0000 0000 0010 0101 1010 1100
*
*
* 0b 0010 0101 1010 1100 0011 1111 0010 1110
* ^
* 0b 0000 0000 0000 0000 0010 0101 1010 1100
*
* 异或的结果 :
* 0b 0010 0101 1010 1100 0001 1010 1000 0010
*/
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
7:扩容的方式不一样
- HashTable :old*2+1
- HashMap :2的指数 增加