HashMap And HashTable

HashMap And HashTable

HashMap和Hashtable两个类都实现了Map接口,两者保存K-V对(key-value对);HashSet则实现了Set接口,性质相似于集合。Hashtable的应用很是普遍,HashMap是新框架中用来代替Hashtable的类,也就是说建议使用HashMap,不要使用Hashtable。可能你以为Hashtable很好用,为何不用呢?这里简单分析他们的区别。java

1、继承的父类不一样api

Hashtable继承自Dictionary类,而HashMap继承自AbstractMap类,HashMap是Java1.2引进的Mapinterface 的一个实现。但两者都实现了Map接口。数组

public class Hashtable<K,V>
    extends Dictionary<K,V>
    implements Map<K,V>, Cloneable, java.io.Serializable {

public class HashMap<K,V> extends AbstractMap<K,V>
    implements Map<K,V>, Cloneable, Serializable {复制代码

2、线程安全性不一样安全

Hashtable 中的方法是Synchronize的,而HashMap中的方法在缺省状况下是非Synchronize的。在多线程并发的环境下,能够直接使用Hashtable,不须要本身为它的方法实现同步,但使用HashMap时就必需要本身增长同步处理。多线程

HashTable并发

public synchronized boolean isEmpty() {
    return count == 0;
}复制代码

HashMapapp

public boolean isEmpty() {
    return size == 0;
}复制代码

3、是否提供contains方法框架

HashMap把Hashtable的contains方法去掉了,改为containsValue和containsKey,由于contains方法容易让人引发误解。Hashtable则保留了contains,containsValue和containsKey三个方法,其中contains和containsValue功能相同,实际上containsValue调用的是contains方法。学习

public synchronized boolean contains(Object value) {
    if (value == null) {
        throw new NullPointerException();
    }

    Entry<?,?> tab[] = table;
    for (int i = tab.length ; i-- > 0 ;) {
        for (Entry<?,?> e = tab[i] ; e != null ; e = e.next) {
            if (e.value.equals(value)) {
                return true;
            }
        }
    }
    return false;
}

public boolean containsValue(Object value) {
    return contains(value);
}复制代码

4、key和value是否容许null值this

其中key和value都是对象,而且不能包含重复key,但能够包含重复的value。Hashtable中,key和value都不容许出现null值。HashMap中,null能够做为键,这样的键只有一个;能够有一个或多个键所对应的值为null。当get()方法返回null值时,多是 HashMap中没有该键,也可能使该键所对应的值为null。所以,在HashMap中不能由get()方法来判断HashMap中是否存在某个键, 而应该用containsKey()方法来判断。

HashTable

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<K,V> entry = (Entry<K,V>)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;
}复制代码

HashMap

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<K,V>[] tab; Node<K,V> 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<K,V> 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<K,V>)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;
}复制代码

5、两个遍历方式的内部实现上不一样

Hashtable、HashMap都使用了 Iterator。而因为历史缘由,Hashtable还使用了Enumeration的方式 。

6、hash值不一样

哈希值的使用不一样,HashTable直接使用对象的hashCode。而HashMap从新计算hash值。

7、内部实现使用的数组初始化和扩容方式不一样

Hashtable和HashMap它们两个内部实现方式的数组的初始大小和扩容的方式。HashTable中hash数组默认大小是11,增长的方式是 old*2+1。HashMap中hash数组的默认大小是16,并且必定是2的指数。

Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的扩展性更好。

咱们可否让HashMap同步?

HashMap能够经过下面的语句进行同步:

Map m = Collections.synchronizeMap(hashMap);复制代码

关于ConcurrentHashMap

public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
    implements ConcurrentMap<K,V>, Serializable {复制代码

Hashtable和HashMap有几个主要的不一样:线程安全以及速度。仅在你须要彻底的线程安全的时候使用Hashtable,而若是你使用Java 5或以上的话,请使用ConcurrentHashMap吧。

若是有兴趣和咱们一块儿讨论问题的话,不妨加下咱们群吧 ,记得加群的时候写上我名字 ID:BigMoreKT:984370849

想要深刻学习的同窗们能够加入QQ群讨论,有全套资源分享,经验探讨,没错,咱们等着你,分享互相的故事!

相关文章
相关标签/搜索