Hashtable和HashMap的区别

来源:互联网 发布:添加删除windows组件 编辑:程序博客网 时间:2024/05/22 08:07

       唉,面试的额时候,十次有八次都会问到Hashtable和HashMap有什么不同,那时候不知道啊,感觉能用会用,能实现就可以了啊,所以也没有考虑那么多。现在有时间,抽个空,查查资料,总结一下这两者的区别,以加强记忆,以防万一。

这两个类具体点说呢,有三个最主要的不同之处,首先,看一下类的定义:

public class HashMap<K, V> extends AbstractMap<K, V> implements Cloneable, Serializable
public class Hashtable<K, V> extends Dictionary<K, V>        implements Map<K, V>, Cloneable, Serializable
从定义上可以看出,两者的父类不一样,Hashtable是继承自陈旧的Dictionary类,而HashMap是继承自AbstractMap。

       其次就是,方法同步的问题,看源码得知,Hashtable的方法基本上都是同步的,而HashMap的方法并不是,也就是说,你可以不采取任何的措施而在多个线程中用一个Hashtable,但是你必须提供外同步才能用HashMap。要想创建一个线程安全的Map对象,可以用Collections类的synchronizedMap()方法实现来返回一个封装的对象。但是这样做也是有坏处的,当你不需要同步的时候,你不能切断HashMap中的同步,而且同步增加的处理费用消耗。
      最后一点不同之处是,HashMap可以允许key与value值是空的,而Hashtable是不可以的。下面看源码:

      HashMap的put方法:    

@Override public V put(K key, V value) {        if (key == null) {            return putValueForNullKey(value);        }        int hash = Collections.secondaryHash(key);        HashMapEntry<K, V>[] tab = table;        int index = hash & (tab.length - 1);        for (HashMapEntry<K, V> e = tab[index]; e != null; e = e.next) {            if (e.hash == hash && key.equals(e.key)) {                preModify(e);                V oldValue = e.value;                e.value = value;                return oldValue;            }        }        // No entry for (non-null) key is present; create one        modCount++;        if (size++ > threshold) {            tab = doubleCapacity();            index = hash & (tab.length - 1);        }        addNewEntry(key, value, hash, index);        return null;    }
(1)上面说过,方法没有同步;(2)通过第2-3行得知,允许key值为null;(3)通过24行看出,并没有对value值做空判断,所以,value值可也为null

现在进到方法putValueForNullKey中看:

    private V putValueForNullKey(V value) {        HashMapEntry<K, V> entry = entryForNullKey;        if (entry == null) {            addNewEntryForNullKey(value);            size++;            modCount++;            return null;        } else {            preModify(entry);            V oldValue = entry.value;            entry.value = value;            return oldValue;        }    }
很明显,一个私有的方法,先判断entry是不为null,即以前是否已经添加过一个key值为null的数据了,没有则新new一个,有则替换旧的value值为新的value。

下面看一下Hashtable的put方法:

    public synchronized V put(K key, V value) {        if (key == null) {            throw new NullPointerException("key == null");        } else if (value == null) {            throw new NullPointerException("value == null");        }        int hash = Collections.secondaryHash(key);        HashtableEntry<K, V>[] tab = table;        int index = hash & (tab.length - 1);        HashtableEntry<K, V> first = tab[index];        for (HashtableEntry<K, V> e = first; e != null; e = e.next) {            if (e.hash == hash && key.equals(e.key)) {                V oldValue = e.value;                e.value = value;                return oldValue;            }        }        // No entry for key is present; create one        modCount++;        if (size++ > threshold) {            rehash();  // Does nothing!!            tab = doubleCapacity();            index = hash & (tab.length - 1);            first = tab[index];        }        tab[index] = new HashtableEntry<K, V>(key, value, hash, first);        return null;    }
(1)方法是同步的;(2)通过2—6行看出,都是对key以及value值做了非空判断,如若是null,抛空指针异常

总结:HashMap是Hashtable轻量级的实现,但是是非线程安全的。两者都实现了Map接口。

           HashMap允许null作为一个key或者value,而Hashtable是不允许的。

           最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自       己为它的方法实现同步,而HashMap 就必须为之提供外同步(Collections.synchronizedMap)。 

      Hashtable和HashMap采用的hash/rehash算法都大概一样,所以性能不会有很大的差异。




0 0
原创粉丝点击