之前写了HashMap的实现原理,因为HashTable实现和HashMap区别并不大,之前偷懒没有再写HashTable的实现,近期发现了一些其他的区别,这里再做一次补充。
不知道HashMap实现原理的同学可以先这个:HashMap实现原理,其中多数重复的实现原理就不再赘述了,本文着重分析两者的区别。
HashTable的实现
HashTable继承自Dictionary,Dictionary是任何保存键值对的类的父类,不过这个类已经过时了。HashMap中继承的是AbstractMap与HashTable有所不同。
与HashMap一致,HashTable也是通过数组和链表存储数据。table, count, threshold, loadFactor这些成员变量都与HashMap作用相同。
数据的遍历、存放等方法都可以在HashMap中看到,这里就不再细说。主要说一下两者的区别:
-
HashMap可以存储value为null的值,同时key也可以为null,HashTable不行
-
HashTable基本上所有的方法都加了synchronized,线程安全,HashMap线程不安全,不过我们可以通过Collections.synchronizedMap()来获取一个包装后线程安全的map
-
Hashtable比HashMap多提供了elments() 和contains() 两个方法。
-
HashTable默认的容量是11,每次扩容2n+1,HashMap初始值为4,每次扩容2n
-
计算key存放位置的方法不同,HashMap效率高,但是冲突更严重
这里着重讲一个两者的区别
HashMap:
int hash = sun.misc.Hashing.singleWordWangJenkinsHash(key); int i = indexFor(hash, table.length); /** * Returns index for hash code h. */ static int indexFor(int h, int length) { // assert Integer.bitCount(length) == 1 : "length must be a non-zero power of 2"; return h & (length-1); } 复制代码
Hashtable:
int hash = hash(key); int index = (hash & 0x7FFFFFFF) % tab.length; private static int hash(Object k) { return k.hashCode(); } 复制代码
可以看到,Hashtable在得到hash之后有进行了一次取余操作,这比较耗时。HashMap因为从一开始就保证了容量为2的幂次放,在得到hash后直接进行了位移运算,这相对Hashtable效率高。但是Hashtable这样做也是有好处的,那就是数据能更离散的存放在table中。