HashTable和HashMap的异同点
不同点:
-
实现的接口继承的类不同:
hashmap:AbstractMap hashtable:Dictionary(Enumerator 提供了特有的key和value的遍历方式)
-
初始数组大小:
hashmap:16 hashtable:11
-
线程安全性
hashmap:非线程安全(在get和remove的同时就会发生冲突,因为这两个方法在同时调用同一个对象) hashtable:线程安全(用了多线程的关键字Synchronize,使原本方法变为上了同步锁的方法,使得在多线程的时候如果某一方法调用了这个对象,则其他方法就不能再次调用只能等上一方法执行完才能够再次调用,从而确保了在同一个时间内只有一个线程调用)
-
扩容方式:
hashmap:resize(2 * table.length);(所以由此看来,hashmap里底层的数组的长度是以2的指数倍增长的,故长度必是2的倍数) hashtable:newCapacity = oldCapacity * 2 + 1 (oldCapacity为底 层数组的长度,所以它的增长方式是:2倍的数组长度加1)
-
null值处理
hashmap:允许key为null(前提:key不能重复),value可以有多个为null,注意:key为null特殊处理,如果key为null,就把数据放到table[0]。 HashMap通过putForNullKey专门处理Key为null的情况(table[0])。 Hashtable:不允许key和value为null。 HashTable的Key不能为空,当用null当做Key的时候会抛出java.lang.NullPointerException异常,因为其在计算Hash的时候调用了key.hashCode();当Key为Null的时候就会抛出异常,而且在put中,并未单独对null进行判断(key不能重复)
-
hash函数不同
Hashmap做如下处理:
int h = hashSeed; if (0 != h && k instanceof String) { return sun.misc.Hashing.stringHash32((Str ing) k); } h ^= k.hashCode(); h ^= (h >>> 20) ^ (h >>> 12); return h ^ (h >>> 7) ^ (h >>> 4);
Hashtable如下:
hashSeed ^ k.hashCode()
-
Hashtable含有一些特有方法
如判断value是否存在containsValue()
相同点:
- 底层数据结构相同:都是用的数组加链表,数组里存链表的头
- 扩容时机相同:count >= threshold (扩容的时候都需要从新哈希)
- 都实现了map接口