Hashtable 与HashMap的区别

来源:互联网 发布:安卓应用知乎 编辑:程序博客网 时间:2024/06/12 01:08

哈希表的数据结构 

     哈希表是一个数组和链表的结合体(在数据结构称“链表散列“),如下图示:

当我们往哈希表中插入元素的时候,先根据key的hash值得到这个元素在数组中的位置(即下标),然后就可以把这个元素放到对应的位置中 了。如果这个元素所在的位子上已经存放其他元素了,那么在同一个位子上的元素将以链表的形式存放,新加入的放在链头,最先加入的放在链尾。

HashMap 和Hashtable是哈希表的具体实现。

HashMap中put方法的实现:

[plain] view plain copy
  1. <span style="font-family:FangSong_GB2312;font-size:18px;"><span style="font-family:FangSong_GB2312;font-size:18px;">public synchronized V put(K key, V value) {  
  2.         // Make sure the value is not null  
  3.         if (value == null) {  
  4.             throw new NullPointerException();  
  5.         }  
  6.   
  7.         // Makes sure the key is not already in the hashtable.  
  8.         Entry tab[] = table;            //把哈希表中数组地址赋值给tab  
  9.         int hash = key.hashCode();      //获得哈希码  
  10.         int index = (hash & 0x7FFFFFFF) % tab.length;   //通过哈希码对数组长  
  11.                                                         //度取余的方法获得数组中的下标  
  12.         for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {    //元素变量指向数组中第index个变量  
  13.                                                             //如果不空,说明已经有元素存在,判断是否要找的元素,直到最后。  
  14.             if ((e.hash == hash) && e.key.equals(key)) {//如果该元素已经存在, 则修改成新值,并返回旧值  
  15.             V old = e.value;  
  16.             e.value = value;  
  17.             return old;  
  18.             }  
  19.         }  
  20.   
  21.         modCount++;         //改良次数加一  
  22.         if (count >= threshold) {  
  23.             // Rehash the table if the threshold is exceeded  
  24.             rehash();  
  25.   
  26.                 tab = table;  
  27.                 index = (hash & 0x7FFFFFFF) % tab.length;  
  28.         }  
  29.   
  30.         // Creates the new entry.如果元素不存在则添加新元素  
  31.         Entry<K,V> e = tab[index];  
  32.         tab[index] = new Entry<K,V>(hash, key, value, e);  
  33.         count++;  
  34.         return null;  
  35.         }</span></span>  


hashMap中put方法的实现:

[plain] view plain copy
  1. <span style="font-family:FangSong_GB2312;font-size:18px;"><span style="font-family:FangSong_GB2312;font-size:18px;"><pre name="code" class="java">public V put(K key, V value) {  
  2.      if (key == null)            //如果是空key则不允许插入  
  3.          return putForNullKey(value);  
  4.      int hash = hash(key.hashCode());    //获得哈希码  
  5.      int i = indexFor(hash, table.length);    //获得数组下标  
  6.      for (Entry<K,V> e = table[i]; e != null; e = e.next) {        //通过hash和key判断此元素是否在hashMap中存在,  
  7.                                                                  //存在修改新值返回旧值  
  8.          Object k;  
  9.          if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {  
  10.              V oldValue = e.value;  
  11.              e.value = value;  
  12.              e.recordAccess(this);  
  13.              return oldValue;  
  14.          }  
  15.      }  
  16.   
  17.      modCount++;  
  18.      //如果hashMap中不存在此元素,则添加  
  19.      addEntry(hash, key, value, i);  
  20.      return null;  
  21.  }</span></span>  

HashTable和HashMap区别

    第一,继承不同。

    public class Hashtable extends Dictionary implements Map
    public class HashMap  extends AbstractMap implements Map

    第二

    Hashtable 中的方法是同步的,而HashMap中的方法在缺省情况下是非同步的。在多线程并发的环境下,可以直接使用Hashtable,但是要使用HashMap的话就要自己增加同步处理了。

    第三

    Hashtable中,key和value都不允许出现null值。

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

    第四,两个遍历方式的内部实现上不同。

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

    第五

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

    第六

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

 

HashMap的使用:
[java] view plain copy
  1. <span style="font-family:FangSong_GB2312;font-size:18px;">import java.util.HashMap;  
  2. import java.util.Iterator;  
  3. import java.util.Map;  
  4. import org.junit.Test;  
  5.   
  6. public class Test3 {  
  7.     @Test  
  8.     public void test3() {  
  9.         Map map = new HashMap();  
  10.         map.put("语文""90");  
  11.         map.put("语文""80");//value 80 将替代 90  
  12.         map.put("数学""85");  
  13.         map.put("英语""90");  
  14.   
  15.         Iterator iter = map.entrySet().iterator();  
  16.         while (iter.hasNext()) {  
  17.             Map.Entry entry = (Map.Entry) iter.next();  
  18.             Object key = entry.getKey();  
  19.             Object val = entry.getValue();  
  20.             System.out.println(entry);  
  21.         }  
  22.     }  
  23.   
  24. }</span>  

输出结果:

       语文=80
       英语=90
       数学=85
1 0
原创粉丝点击