HashMap与HashTable主要区别

Map接口源代码如下:

public interface Map<K,V> {
   boolean containsKey(Object key);
   boolean containsValue(Object value);
   V get(Object key);
   V put(K key, V value);
   V remove(Object key);

   // @param m mappings to be stored in this map.
   void putAll(Map<? extends K, ? extends V> m);

   void clear();

   // @return a set view of the keys contained in this map.
   Set<K> keySet();

   Collection<V> values();

   // @return a set view of the mappings contained in this map.
   Set<Map.Entry<K, V>> entrySet();

   boolean equals(Object o);
   int hashCode();

   interface Entry<K,V> {
       K getKey();
       V getValue();
       V setValue(V value);
       boolean equals(Object o);
       int hashCode();
   }
}

          
   
   

AbstractMap源代码如下:

public abstract class AbstractMap<K,V> implements Map<K,V> {
   
    protected AbstractMap() { }

    public int size() {
        return entrySet().size();
    }

    public boolean isEmpty() {
        return size() == 0;
    }

    /**
     * This implementation iterates over entrySet searching
     * for an entry with the specified value.  If such an entry is found,
     * true is returned.  If the iteration terminates without
     * finding such an entry, false is returned.  Note that this
     * implementation requires linear time in the size of the map.
     *
     * @throws ClassCastException 
     * @throws NullPointerException 
     */
    public boolean containsValue(Object value) {
        Iterator<Entry<K,V>> i = entrySet().iterator();
        if (value==null) {
            while (i.hasNext()) {
                Entry<K,V> e = i.next();
                if (e.getValue()==null)
                    return true;
            }
        } else {
            while (i.hasNext()) {
                Entry<K,V> e = i.next();
                if (value.equals(e.getValue()))
                    return true;
            }
        }
        return false;
    }

    /**
     *This implementation iterates over entrySet() searching
     * for an entry with the specified key.  If such an entry is found,
     * true is returned.  If the iteration terminates without
     * finding such an entry, false is returned.  Note that this
     * implementation requires linear time in the size of the map; many
     * implementations will override this method.
     *
     * @throws ClassCastException   
     * @throws NullPointerException
     */
    public boolean containsKey(Object key) {
        Iterator<Map.Entry<K,V>> i = entrySet().iterator();
        if (key==null) {
            while (i.hasNext()) {
                Entry<K,V> e = i.next();
                if (e.getKey()==null)
                    return true;
            }
        } else {
            while (i.hasNext()) {
                Entry<K,V> e = i.next();
                if (key.equals(e.getKey()))
                    return true;
            }
        }
        return false;
    }

    /**
     *This implementation iterates over entrySetsearching
     * for an entry with the specified key.  If such an entry is found,
     * the entry's value is returned.  If the iteration terminates without
     * finding such an entry, null is returned.  Note that this
     * implementation requires linear time in the size of the map; many
     * implementations will override this method.
     *
     * @throws ClassCastException          
     * @throws NullPointerException       
     */
    public V get(Object key) {
        Iterator<Entry<K,V>> i = entrySet().iterator();
        if (key==null) {
            while (i.hasNext()) {
                Entry<K,V> e = i.next();
                if (e.getKey()==null)
                    return e.getValue();
            }
        } else {
            while (i.hasNext()) {
                Entry<K,V> e = i.next();
                if (key.equals(e.getKey()))
                    return e.getValue();
            }
        }
        return null;
    }


    // Modification Operations

    /**
     * <p>This implementation always throws an
     * UnsupportedOperationException.
     *
     * @throws UnsupportedOperationException 
     * @throws ClassCastException         
     * @throws NullPointerException
     * @throws IllegalArgumentException     
     */
    public V put(K key, V value) {
        throw new UnsupportedOperationException();
    }

    /**
     * This implementation iterates over entrySet() searching for an
     * entry with the specified key.  If such an entry is found, its value is
     * obtained with its getValue operation, the entry is removed
     * from the collection (and the backing map) with the iterator's
     * remove operation, and the saved value is returned.  If the
     * iteration terminates without finding such an entry, null is
     * returned.  Note that this implementation requires linear time in the
     * size of the map; many implementations will override this method.
     *
     * <p>Note that this implementation throws an
     * UnsupportedOperationException if the entrySet
     * iterator does not support the remove method and this map
     * contains a mapping for the specified key.
     *
     * @throws UnsupportedOperationException 
     * @throws ClassCastException     
     * @throws NullPointerException       
     */
    public V remove(Object key) {
        Iterator<Entry<K,V>> i = entrySet().iterator();
        Entry<K,V> correctEntry = null;
        if (key==null) {
            while (correctEntry==null && i.hasNext()) {
                Entry<K,V> e = i.next();
                if (e.getKey()==null)
                    correctEntry = e;
            }
        } else {
            while (correctEntry==null && i.hasNext()) {
                Entry<K,V> e = i.next();
                if (key.equals(e.getKey()))
                    correctEntry = e;
            }
        }

        V oldValue = null;
        if (correctEntry !=null) {
            oldValue = correctEntry.getValue();
            i.remove();
        }
        return oldValue;
    }


    // Bulk Operations

    /**
     * This implementation iterates over the specified map's
     * entrySet() collection, and calls this map's put
     * operation once for each entry returned by the iteration.
     *
     * Note that this implementation throws an
     * UnsupportedOperationException if this map does not support
     * the put operation and the specified map is nonempty.
     *
     * @throws UnsupportedOperationException 
     * @throws ClassCastException    
     * @throws NullPointerException         
     * @throws IllegalArgumentException    
     */
    public void putAll(Map<? extends K, ? extends V> m) {
        for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
            put(e.getKey(), e.getValue());
    }

    /**
     * This implementation calls entrySet().clear().
     *
     * Note that this implementation throws an
     * UnsupportedOperationException if the entrySet
     * does not support the clear operation.
     *
     * @throws UnsupportedOperationException 
     */
    public void clear() {
        entrySet().clear();
    }
    ..............
 }

HashMap源代码如下:

public class HashMap<K,V>
    extends AbstractMap<K,V>
    implements Map<K,V>, Cloneable, Serializable
{  .........  }

Hashtable的源代码如下:

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

    /**
     * The hash table data.
     */
    private transient Entry<K,V>[] table;

    /**
     * The total number of entries in the hash table.
     */
    private transient int count;
    
    .............
}

 HashTable的应用非常广泛,HashMap是新框架中用来代替HashTable的类,也就是说建议使用HashMap,不要使用HashTable。可能你觉得HashTable很好用,为什么不用呢?这里简单分析他们的区别。

1.Hashtable中的方法是同步的,而HashMap中的方法在缺省情况下是非同步的。即是说,在多线程应用程序中,不用专门的操作就安全地可以使用Hashtable了;而对于HashMap,则需要额外的同步机制。但HashMap的同步问题可通过Collections的一个静态方法得到解决:
Map Collections.synchronizedMap(Map m),这个方法返回一个同步的Map,这个Map封装了底层的HashMap的所有方法,使得底层的HashMap即使是在多线程的环境中也是安全的。

2.HashTable不允许null值(key和value都不可以),在HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。当get()方法返回null值时,即可以表示HashMap中没有该键,也可以表示该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键,而应该用containsKey()方法来判断。

3.HashTable有一个contains(Object value),功能和containsValue(Object value)功能一样。

4.HashTable使用Enumeration,HashMap使用Iterator。Hashtable是基于陈旧的Dictionary类的,HashMap是Java 1.2引进的Map接口的一个实现。

以上只是表面的不同,它们的实现也有很大的不同。

5.HashTable中hash数组默认大小是11,增加的方式是 old*2+1。HashMap中hash数组的默认大小是16,而且一定是2的指数。

6.哈希值的使用不同,HashTable直接使用对象的hashCode,代码是这样的:

int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length; 

而HashMap重新计算hash值,而且用与代替求模:

int hash = hash(k); 

int i = indexFor(hash, table.length);


static int hash(Object x) {  

 int h = x.hashCode();
 h += ~(h << 9);   
  h ^= (h >>> 14);   
  h += (h << 4);   
  h ^= (h >>> 10);   

  return h; 

} 

static int indexFor(int h, int length) {   
    return h & (length-1); 
} 

以上只是一些比较突出的区别,当然他们的实现上还是有很多不同的,比如 HashMap对null的操作。

原文地址:https://www.cnblogs.com/likai198981/p/2851353.html