Java基础知识学习总结(四)---Hashtable和HashMap的区别与联系分析

日期: 2016-9-17


内容: Hashtable和HashMap的区别与联系分析


一、源码解析:

1、类的声明:


查看HashTable的源码如下:

public class Hashtable
    extends Dictionary
    implements Map, Cloneable, java.io.Serializable 

HashMap的源码如下:

public class HashMap extends AbstractMap
    implements Map, Cloneable, Serializable {

总结一:

联系:

两个类都实现了 Map, Cloneable, java.io.Serializable这三个接口。


区别:

Hashtable继承了Dictionary类,然而HashMap继承了AbstractMap类。


2、方法的声明:

Hashtable的put方法如下:

 public synchronized V put(K key, V value) {//
        // Make sure the value is not null
        if (value == null) {		    //
            throw new NullPointerException();
        }

        // Makes sure the key is not already in the hashtable.
        Entry tab[] = table;
        int hash = key.hashCode();	   //
        int index = (hash & 0x7FFFFFFF) % tab.length;
        @SuppressWarnings("unchecked")
        Entry entry = (Entry)tab[index];
        for(; entry != null ; entry = entry.next) {
            if ((entry.hash == hash) && entry.key.equals(key)) {
                V old = entry.value;
                entry.value = value;
                return old;
            }
        }

        addEntry(hash, key, value, index);
        return null;
    }
源代码中标记红的解释如下:
①、表示方法是同步的。即适合在多线程的操作中使用。
②、表示该方法不允许操作的值为空,一旦值为空就会抛出异常。
③、该方法调用了Ksy的hashCode方法,一旦key值为null的话就会抛出空指针异常。

HashMap的put方法如下:

public V put(K key, V value) {		//
        return putVal(hash(key), key, value, false, true);
    }


    final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node[] tab; Node p; int n, i;
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;
        if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);
        else {
            Node e; K k;
            if (p.hash == hash &&
                ((k = p.key) == key || (key != null && key.equals(k))))
                e = p;
            else if (p instanceof TreeNode)
                e = ((TreeNode)p).putTreeVal(this, tab, hash, key, value);
            else {
                for (int binCount = 0; ; ++binCount) {
                    if ((e = p.next) == null) {
                        p.next = newNode(hash, key, value, null);
                        if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                            treeifyBin(tab, hash);
                        break;
                    }
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        break;
                    p = e;
                }
            }
            if (e != null) { // existing mapping for key
                V oldValue = e.value;
                if (!onlyIfAbsent || oldValue == null)
                    e.value = value;
                afterNodeAccess(e);
                return oldValue;
            }
        }
        ++modCount;
        if (++size > threshold)
            resize();
        afterNodeInsertion(evict);
        return null;
    }

区别与Hashtable的HashMap具有如下的优点:

①、HashMap:方法的声明是非同步的;

②、方法允许key值为null;

③、方法并没有对value进行任何调用,所以允许为null。

补充: 
Hashtable 有一个 contains方法,容易引起误会,所以在HashMap里面已经去掉了
当然,2个类都用containsKey和containsValue方法。

总结二:


HashMap                Hashtable

父类                  AbstractMap          Dictiionary

是否同步            否                            是

k,v可否null     是                            否


二、代码测试性能谁比较高:

package java8.java.lang.hashmap;

import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

public class HashMapTest {


	public static void main(String[] args) {

		/**
		 * 测试HashMap、HashTable的区别与联系
		 */
		testHashTable();
		testHashMap();
	}
	
	/**
	 * 测试Hashtable的性能
	 * 
	 * @parameter
	 */
	public static void testHashTable()
	{
		//获得当前时间戳
		long time1 = System.currentTimeMillis();
		
		//实例化一个Hashtable实例
		Hashtable hashTable = new Hashtable();
		
		//获得一个String数组
		String[] str = new String[]{"Tom","Jack","Jim","David","Jackson","Tomsin","Voidc","Mission","Limn","liuHasi"};
		
		//将sb的数据放入hashTable中:调用Hashtable的put方法
		for (int j = 0; j < 10000; j++) {
			for (int i = 0; i < str.length; i++) {
				hashTable.put(i, str[i]);
			}
			
		}
		//获得程序执行之后的时间
		long time2 = System.currentTimeMillis();
		
		//打印执行hashTable的put方法的时间差
		System.out.println("执行HashTable的put方法的时间为: "+(time2 - time1));
	}
	
	/**
	 * 测试HashMap的性能
	 * 
	 * @parameter
	 */
	public static void testHashMap()
	{
		//获得当前时间戳
		long time1 = System.currentTimeMillis();
		
		//实例化一个Hashtable实例
		HashMap hashMap = new HashMap();
		
		//获得一个String数组
		String[] str = new String[]{"Tom","Jack","Jim","David","Jackson","Tomsin","Voidc","Mission","Limn","liuHasi"};
		
		//将sb的数据放入hashTable中:调用Hashtable的put方法
		for (int j = 0; j < 10000; j++) {
			for (int i = 0; i < str.length; i++) {
				hashMap.put(i, str[i]);
			}
		}

		//获得程序执行之后的时间
		long time2 = System.currentTimeMillis();
		
		//打印执行hashTable的put方法的时间差
		System.out.println("执行HashMap的put方法的时间为: "+(time2 - time1));
	}

}

由于数据有限,所以测试代表性不是很强,因此我只能跑十次到三十次取平均值之后发现:HasMap的性能确实要比Hashtable要高一些。而且这种优势可能在处理数据量较大的业务中比较突出。

执行HashTable的put方法的时间为: 25
执行HashMap的put方法的时间为: 19


三、总结:Hashtable和HashMap的主要区别有如下几点:

1、Hashtable适用于多线程(同步)操作中,hashMap适用于单线程(非同步)的场合中。

2、HashMap允许将null作为一个entry的key或者value,而Hashtable不允许。

3、主要区别在于HashMap允许空(null)键值(key),由于非线程安全,效率上可能高于Hashtable。

4、HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因为contains方法容易让人引起误解。

5、Hashtable继承自Dictionary类,而HashMap是Java1.2引进的Map interface的一个实现。

6、最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就 必须为之提供外同步(Collections.synchronizedMap)(这和我们说的第一点一样)。












你可能感兴趣的:(Java基础知识学习总结)