java中HashMap与HashTable

一、历史区别

HashTable产生于JDK 1.1,而HashMap产生于JDK 1.2。

二、实现接口和继承的父类


可以看出HashTable多了dictionary的继承,二hashmap则是继承的AbstractMap,且通过AbstractMap实现了Map接口。

而现在Dictionary类已经被废弃。他的contains()方法和containsValue()的功能一致。

三、null key 和 null value

hashmap支持两者,而HashTable两者都不支持,一旦出现则跑出异常Nullpointerexception。

四、实现机制

HashTable默认的初始大小为11,之后每次扩充为原来的2n+1。HashMap默认的初始化大小为16,之后每次扩充为原来的2倍。就是如果在创建时给定了初始化大小,那么HashTable会直接使用你给定的大小,而HashMap会将其扩充为2的幂次方大小。

也就是说HashTable会尽量使用素数、奇数。而HashMap则总是使用2的幂作为哈希表的大小。我们知道当哈希表的大小为素数时,简单的取模哈希的结果会更加均匀,所以单从这一点上看,HashTable的哈希表大小选择,似乎更高明些。但另一方面我们又知道,在取模计算时,如果模数是2的幂,那么我们可以直接使用位运算来得到结果,效率要大大高于做除法。所以从hash计算的效率上,是HashMap更胜一筹。HashTable的空间利用明显较高,但是由于hashmap的自动扩容和现在硬件上内存和外存的提升,所以HashTable的优势并不明显。

所以,事实就是HashMap为了加快hash的速度,将哈希表的大小固定为了2的幂。当然这引入了哈希分布不均匀的问题,所以HashMap为解决这问题,又对hash算法做了一些改动。在1.8之后,对于哈希冲突采用了红黑树的方式提高了查询效率。

五、线程安全

HashTable对于公开的函数头采用了synchronized关键字,而遍历视图比如keySet都使用了Collections.synchronizedXXX进行了同步包装。所以HashTable线程安全的,而hashmap没有。所以使用hashmap需要额外的提供同步。

六、后续

HashTable因为dictionary的废弃,还有效率较hashmap较低,以及HashTable在空间利用的优势并不大,所以不太建议使用HashTable。但是java仍然保持了对HashTable的维护,因为曾经的硬件没有现在那么好,对于哈希冲突的处理不够成熟,所以HashTable的使用量仍然很大,为了原来的程序的使用,java在更新中持续了对HashTable的维护。

个人认为,现在很多面试官面试的时候喜欢问两者的区别,应该是之前的两者优势对比并不明显,确实需要针对情况仔细考虑如何使用。

该文章很大一部分引用了http://www.importnew.com/24822.html的内容。

猜你喜欢

转载自blog.csdn.net/astar3/article/details/80639004