读书人

HashMap跟Hashtable的比较

发布时间: 2013-01-27 13:56:15 作者: rapoo

HashMap和Hashtable的比较
/** * Hashtable的put方法,是同步的,可以在多线程环境下确保原子性执行,index值的计算过程非常简单, * 但是运气不好的话有可能得到大量重复的index,大量的key-value存储在相同的Entry链表中,从而降 * 低了get操作的执行效率 */public synchronized V put(K key, V value) {// Make sure the value is not nullif (value == null) { throw new NullPointerException();}// Makes sure the key is not already in the hashtable.Entry tab[] = table;//得到哈希值int hash = key.hashCode();/* 通过哈希值获取index */int index = (hash & 0x7FFFFFFF) % tab.length;/* 遍历Entry链表 */for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {/* 注意这里不仅要比较哈希值还要比较key对象 */ if ((e.hash == hash) && e.key.equals(key)) {V old = e.value;e.value = value;return old;}}modCount++;/* 如果装不下了,就扩充容量,重新获取index */if (count >= threshold) { // Rehash the table if the threshold is exceeded rehash();tab = table;index = (hash & 0x7FFFFFFF) % tab.length;}/* 如果根据哈希值没找到对应的entry对象,在entry链表末尾加入新的entr对象 */Entry<K,V> e = tab[index];tab[index] = new Entry<K,V>(hash, key, value, e);count++;return null;}

?

2.HashMap的put方法及其使用的相关方法实现代码,以下做了注释:/** * 使用位移算法对哈希码给予补充,防止出现大量的0、1重复,这样得到的index重复的几率就很大,经过补充位移运算后, * 可以使哈希码的0、1分布更加均匀,再经过indexFor()方法计算得到的index重复的几率就小很多,这就是HashMap散列 * 算法相比于Hashtable的哈希算法更优化的关键所在。 * 需要注意的是key=null时,index=0。 */static int hash(int h) {h ^= (h >>> 20) ^ (h >>> 12);return h ^ (h >>> 7) ^ (h >>> 4);}/** * 通过哈希值和table的最大存储位置的位与运算,得到一个小于length的值作为index。 */static int indexFor(int h, int length) {return h & (length-1);}/** * HashMap的put方法 */public V put(K key, V value) {if (key == null)return putForNullKey(value);//得到哈希值,hashCode()方法为native方法,估计是C、C++或者汇编实现的int hash = hash(key.hashCode());//得到indexint i = indexFor(hash, table.length);/* 得到index,遍历table[index]寻找key相同的对象,如果不存在增加一个Entry对象 */for (Entry<K,V> e = table[i]; e != null; e = e.next) {Object k;/* 注意这里不仅要比较哈希值还要比较key对象,找到后覆盖原来的值 */if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {V oldValue = e.value;e.value = value;e.recordAccess(this);return oldValue;}}/* 如果根据哈希值没找到对应的entry对象,在entry链表末尾加入新的entr对象 */modCount++;addEntry(hash, key, value, i);return null;}?3.下面比较一下两个类到底有什么异同。
相同点:
(1)这两个类存储key-value对象的数据结构基本相同,都是将
key-value封装在entry对象中,entry中有指向下一个entry对象的引用(Entry next),这样就可以形成一个链表,而在类的主体中保存了一个Entry链表的数组(Entry[] table)来存储Entry对象,具体存储结构如下图:
?不同点;
通过比较两个类put方法的实现,我们会发现它们之间的区别:
(1)Hashtable的put方法有synchronized修饰,说明该put方法实现了同步,达到了一定的线程安全级别,
而HashMap的put方式没有实现同步,是非线程安全类,当然,单线程情况下,HashMap无疑拥有更好的执行效率而不用去考虑线程安全问题。
(2)通过key获取index的过程有很大差别,其实这是两个类最重要的区别,在代码的注释里面已经给出了分析,HashMap的实现方式无疑使一种更优的实现,所以我们在单线程的环境下,或者在某些安全的多线程环境下都应该优先使用HashMap。当然,并发环境下,我们还可以考虑使用NIO包里面的类,这个问题将在其他的文章里讨论。

读书人网 >编程

热点推荐