HashMap 和 HashTable 区别

不同点:

1. HashMap允许空(null)键值(key),Hashtable不行

HashMap map = new HashMap();  //HashMap
map.put("a", null);
map.put(null, "b");    
map.put(null, null);  //编译运行,都可以
		
Hashtable table = new Hashtable();  //HashTable
table.put("a", null);      //编译正常,运行时空指针异常,键或值都不能为空
table.put(null, "123");    //同上

2. HashMap把Hashtable的contains方法去掉了。也有 containsvalue和containsKey方法

map.containsValue("");   //查询是否有值为""的数据
map.containsKey("");     //查询键

table.contains("");       //查询值,和下面的重复,容易造成误解,所以HashMap去掉了
table.containsValue("");  //查询值
table.containsKey("");   //查询键       都返回false或true

3. 历史原因:Hashtable是基于陈旧的Dictionary类的,HashMap是Java 1.2引进的Map接口的一个实现

Hashtable是Dictionary的子类,HashMap是Map接口的一个实现类

HashMap<K,V> extends AbstractMap<K,V>
			 implements Map<K,V>, Cloneable, Serializable

Hashtable<K,V>  extends Dictionary<K,V>  
				implements Map<K,V>, Cloneable, Serializable

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

Map m = Collections.synchronizedMap(new HashMap()); //HashMap同步的方法,使在多线程中也安全

(这个方法返回一个同步的Map,这个Map封装了底层的HashMap的所有方法)

(线程同步,安全;线程不同步,不安全)





<!--[if !vml]-->
<!--[endif]-->
HashMap
Hashtable
继承,实现
HashMap <K,V>    
extends  AbstractMap<K,V>    
implements Map<K,V>, Cloneable, Serializable
Hashtable <K,V>
  extends  Dictionary<K,V>
  implements  Map<K,V>, Cloneable,Serializable
多线程,同步
未同步的,可以使用 Colletcions 进行同步
Map Collections.synchronizedMap(Map m)
已经同步过的可以安全使用
对null的处理
HashMap map =  new  HashMap();
map.put( null "Null" );
map.put( "Null" null );
map.containsKey( null );
map.containsValue( null );
以上这 5 条语句无论在编译期,还是在运行期都是没有错误的 .
在HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。当get()方法返回null值时,即可以表示 HashMap中没有该键,也可以表示该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键, 而应该用containsKey()方法来判断。
Hashtable table = new Hashtable();
table.put(null, "Null");
table.put("Null", null);
table.contains(null);
table.containsKey(null);
table.containsValue(null);
后面的 5 句话在编译的时候不会有异常,可在运行的时候会报空指针异常
具体原因可以查看源代码
public synchronized V put(K key, V value) {
     // Make sure the value is not null
     if (value == null) {
         throw new NullPointerException();
     }
………….
增长率
void  addEntry( int  hash, K key, V value, int  bucketIndex) {
      Entry<K,V> e =  table [bucketIndex];
         table [bucketIndex] =  new Entry<K,V>(hash, key, value, e);
         if  ( size ++ >=  threshold )
            resize(2 *  table . length );
    }
protectedvoid  rehash() {
       int  oldCapacity = table . length ;
      Entry[] oldMap =  table ;
       int  newCapacity = oldCapacity * 2 + 1;
      Entry[] newMap =  new Entry[newCapacity];
       modCount ++;
       threshold  = ( int )(newCapacity *  loadFactor );
       table  = newMap;
       for  ( int  i = oldCapacity ; i-- > 0 ;) {
           for  (Entry<K,V> old = oldMap[i] ; old !=  null  ; ) {
           Entry<K,V> e = old;
           old = old. next ;
            int  index = (e. hash  & 0x7FFFFFFF) % newCapacity;
           e. next  = newMap[index];
           newMap[index] = e;
          }
      }
    }
 
哈希值的使用
HashMap 重新计算 hash 值,而且用与代替求模
      publicboolean  containsKey(Object key) {
              Object k = maskNull(key);
               int  hash = hash(k.hashCode());
               int  i = indexFor(hash, table.length);
              Entry e = table[i];
               while  (e !=  null ) {
                   if  (e.hash == hash && eq(k, e.key))
                       returntrue ;
                  e = e.next;
              }
               return false ;
          }
HashTable 直接使用对象的 hashCode ,代码是这样的:
publicsynchronizedboolean containsKey(Object key) {
      Entry tab[] =  table ;
       int  hash = key.hashCode();
       int  index = (hash & 0x7FFFFFFF) % tab. length ;
       for  (Entry<K,V> e = tab[index] ; e !=  null  ; e = e. next ) {
           if  ((e. hash  == hash) && e. key .equals(key)) {
            return true ;
          }
      }
       return false ;
    }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值