hashtableとhashmapの違い

4598 ワード

HashMapとHashtableはいずれもMapインタフェースを実現した.主な違いは、スレッドセキュリティ、同期(synchronization)、および速度です.
 
まず2つのクラスの定義を見てみましょう
 hashtable:
public class Hashtable  
    extends Dictionary  
    implements Map, Cloneable, java.io.Serializable 

 hashMap
public class HashMap  
    extends AbstractMap  
    implements Map, Cloneable, Serializable 

 
HashtableはDictiionaryから継承され、HashMapはAbstractMapから継承されていることがわかります.
 
Hashtableのputメソッドは次のとおりです.
 
public synchronized V put(K key, V value) {  //######  1  
  // Make sure the value is not null  
  if (value == null) { //######   2  
    throw new NullPointerException();  
  }  
  // Makes sure the key is not already in the hashtable.  
  Entry tab[] = table;  
  int hash = key.hashCode(); //######   3  
  int index = (hash & 0x7FFFFFFF) % tab.length;  
  for (Entry e = tab[index]; e != null; e = e.next) {  
    if ((e.hash == hash) && e.key.equals(key)) {  
      V old = e.value;  
      e.value = value;  
      return old;  
    }  
  }  
  modCount++;  
  if (count >= threshold) {  
    // Rehash the table if the threshold is exceeded  
    rehash();  
    tab = table;  
    index = (hash & 0x7FFFFFFF) % tab.length;  
  }  
  // Creates the new entry.  
  Entry e = tab[index];  
  tab[index] = new Entry(hash, key, value, e);  
  count++;  
  return null;  
}  

 
 
注意1メソッドは同期の注意2メソッドvalue=null注意3メソッドはkeyのhashCodeメソッドを呼び出し、key=nullの場合、空のポインタ異常HashMapのputメソッドは次のように放出されます.
HashMapのputメソッドは次のとおりです.
public V put(K key, V value) { //######   1  
  if (key == null)  //######   2  
    return putForNullKey(value);  
  int hash = hash(key.hashCode());  
  int i = indexFor(hash, table.length);  
  for (Entry e = table[i]; e != null; e = e.next) {  
    Object k;  
    if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {  
      V oldValue = e.value;  
      e.value = value;  
      e.recordAccess(this);  
      return oldValue;  
    }  
  }  
  modCount++;  
  addEntry(hash, key, value, i);  //######     
  return null;  
}  

 
 
注意1メソッドが非同期である注意2メソッドはkey=null注意3メソッドがvalueを呼び出していないのでnullを許可する
補足:Hashtableにはcontainsメソッドがあり、誤解を招きやすいので、HashMapではすでに削除されています.もちろん、2つのクラスはcontainsKeyとcontainsValueメソッドを使用しています.
 

HashMapとHashtableの違い


1:HashMapとHashtableはいずれもMapインタフェースを実現しているが,どちらを使うかを決める前にそれらの違いを明らかにする.主な違いは、スレッドセキュリティ、同期(synchronization)、および速度です.
2:HashMapはHashtableにほぼ等価であり、HashMapがsynchronizedでない場合を除きnull(HashMapはnullのキー値(key)と値(value)として受け入れることができ、Hashtableはできない)を受け入れることができる.
3:HashMapは非synchronizedであり、Hashtableはsynchronizedであり、これはHashtableがスレッドが安全であり、複数のスレッドが1つのHashtableを共有できることを意味する.正確な同期がなければ、複数のスレッドはHashMapを共有できません.Java 5は、HashTableの代わりに、HashTableの拡張性よりも優れたConcurrentHashMapを提供します.
4:HashMapの反復器(Iterator)はfail-fast反復器であり、Hashtableのenumerator反復器はfail-fastではない.したがって、他のスレッドがHashMapの構造(要素を追加または削除)を変更すると、ConcurrentModificationExceptionが放出されますが、反復器自体のremove()メソッドで要素を除去すると、5 ConcurrentModificationException異常は放出されません.しかし、これは必ずしも起こる行為ではありません.JVMを見てください.これも同様にEnumerationとIteratorの違いです.
5:Hashtableはスレッドが安全でsynchronizedであるため、単一スレッド環境ではHashMapよりも遅い.同期を必要とせず、単一のスレッドしか必要としない場合は、HashMapを使用するとHashtableよりもパフォーマンスが向上します.
6:HashMapは、時間が経つにつれてMapの要素の順序が変化しないことを保証することはできません.
7:HashTableではhash配列のデフォルトサイズは11であり、増加はold*2+1である.HashMapにおけるhash配列のデフォルトサイズは16であり,必ず2の指数である.

いくつかの重要な用語に注意してください。


1)sychronizedは、Hashtableを変更できるスレッドが1回に1つしかないことを意味する.つまり、任意のスレッドがHashtableを更新する場合は、まず同期ロックを取得し、他のスレッドは、同期ロックが解放されてから再び同期ロック更新Hashtableを取得する必要があります.
2)Fail-safeはiterator反復器に関連している.集合オブジェクトがIteratorまたはListIteratorを作成し、他のスレッドが「構造的」に集合オブジェクトを変更しようとすると、ConcurrentModificationException例外が放出されます.ただし、他のスレッドはset()メソッドでコレクションオブジェクトを変更することは許可されます.これは、構造的にコレクションを変更しないためです.ただし、既に構造から変更が行われている場合はset()メソッドを呼び出すと、IllegalArgumentException例外が放出されます.
3)構造上の変更は、mapの構造に影響を及ぼす要素を削除または挿入することを意味する.

HashMapを同期させることができますか?


HashMapは、次の文で同期することができる:Mapm=Collections.synchronizeMap(hashMap);

結論


HashtableとHashMapには、スレッドのセキュリティと速度の主な違いがあります.完全なスレッドセキュリティが必要な場合のみHashtableを使用し、Java 5以上を使用する場合はConcurrentHashMapを使用しましょう.