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的操作。