HashMap和HashTable异同点及使用场景
HashMap和HashTable异同点及使用场景
线程安全不同
Hashtable是线程安全,HashMap非线程安全。
是否允许null值不同
HashMap可以使用null作为key、value,并且null元素会计入size。
Hashtable不允许null作为key、value,当出现null值会抛出异常。
Hashtable put方法注释:
/** * Maps the specified <code>key</code> to the specified * <code>value</code> in this hashtable. Neither the key nor the * value can be <code>null</code>. <p> **/
继承实现方式不同
HashMap和Hashtable都实现了Map、Cloneable、java.io.Serializable接口。
-
实现了Map接口,意味着它们都支持key-value键值对操作。支持“添加key-value键值对”、“获取key”、“获取value”、“获取map大小”、“清空map”等基本的key-value键值对操作。 实现了Cloneable接口,意味着它能被克隆。 实现了java.io.Serializable接口,意味着它们支持序列化,能通过序列化去传输。
HashMap继承于AbstractMap,而Hashtable继承于Dictionary。
-
Dictionary是一个抽象类,它直接继承于Object类,没有实现任何接口。Dictionary类是JDK 1.0的引入的。虽然Dictionary也支持“添加key-value键值对”、“获取value”、“获取大小”等基本操作,但它的API函数比Map少;而且Dictionary一般是通过Enumeration(枚举类)去遍历,Map则是通过Iterator(迭代器)去遍历。 然而‘由于Hashtable也实现了Map接口,所以,它既支持Enumeration遍历,也支持Iterator遍历。
初始容量和扩容策略不同
HashMap的初始容量为16,Hashtable初始容量为11,两者的填充因子默认都是0.75
HashMap扩容时是当前容量翻倍即:capacity*2,Hashtable扩容时是容量翻倍+1即capacity*2+1
计算hash的方法不同
Hashtable计算hash是直接使用key的hashcode对table数组的长度直接进行取模
int hash = key.hashCode(); int index = (hash & 0x7FFFFFFF) % tab.length;
HashMap计算hash对key的hashcode进行了二次hash,以获得更好的散列值,然后对table数组长度取摸
static int hash(int h) { // This function ensures that hashCodes that differ only by // constant multiples at each bit position have a bounded // number of collisions (approximately 8 at default load factor). h ^= (h >>> 20) ^ (h >>> 12); return h ^ (h >>> 7) ^ (h >>> 4); } static int indexFor(int h, int length) { return h & (length-1); }
使用场景
-
非并发场景使用HashMap,并发场景可以使用Hashtable,但是推荐使用ConcurrentHashMap(锁粒度更低、效率更高)。 另外使用在使用HashMap时要注意null值的判断, Hashtable也要注意防止put null key和 null value。
参考资料:
上一篇:
IDEA上Java项目控制台中文乱码