HashMapとHashtableの違いは?


3750

違いは何ですかHashMapHashtableJavaでは?

スレッド化されていないアプリケーションの方が効率的ですか?


17
HashTableはJava 1.7では廃止されており、ConcurrentMap実装を使用することをお勧めします
MissFiona

@MissFionaいいえ、ConcurrentMapありません。質問は、スレッド化/並列性を意味する「非スレッド・アプリケーションは、」問題ではないと言うように、ここでは必要。
バジルブルク

回答:


3775

HashMapHashtableJavaの間にはいくつかの違いがあります。

  1. Hashtable同期されますが同期されHashMapません。HashMap非同期のオブジェクトは通常、同期されたオブジェクトよりもパフォーマンスが高いため、これはスレッド化されていないアプリケーションに適しています。

  2. Hashtablenullキーまたは値は許可されません。 HashMap1つのnullキーと任意の数のnull値を許可します。

  3. HashMapののサブクラスの一つであるLinkedHashMapので、あなたが(デフォルトで挿入順です)予測可能な繰り返し順序をしたいと思うことをイベントでは、あなたが簡単に入れ替えることができ、HashMapためLinkedHashMap。を使用してHashtableいる場合、これは簡単ではありません。

同期は問題ではないので、お勧めしHashMapます。同期が問題になる場合は、もご覧くださいConcurrentHashMap


84
HashMapをスレッドセーフにしたい場合は、を使用してくださいCollections.synchronizedMap()
RokStrniša

275
また、スレッドセーフへの素朴なアプローチHashtable(「すべてのメソッドを同期することで、同時実行性の問題に対処する必要があります!」)は、スレッドされたアプリケーションにとって非常に悪くなるとコメントします。を外部で同期するHashMap(および結果について考える)か、ConcurrentMap実装を使用する(および並行性のために拡張APIを利用する)方がよいでしょう。結論:使用する唯一の理由Hashtableは、レガシーAPI(1996年頃)がそれを必要とする場合です。
エリクソン2012年

8
HashMapは、プログラマーが実際に使用するときにthreadSafeコードを書く柔軟性を提供します。ConcurrentHashMapやHashTableなどのスレッドセーフなコレクションが必要になることはめったにありませんでした。必要なのは、同期されたブロック内の特定の関数セットまたは特定のステートメントをスレッドセーフにすることです。
Gaurava Agarwal

2
Hashtableは廃止され、非スレッドセーフ環境にHashMapを使用しています。スレッドセーフが必要な場合は、Collections.synchronizedMap()を使用するか、ハッシュテーブルよりも効率的なConcurrentHashMapを使用できます。
Maneesh Kumar 2018

1
それは時代遅れですが非推奨ではなく、なぜこれがそうなのか疑問に思っています。私はこのクラス(および同じ理由でベクター)を削除すると既存のコードが多くなりすぎ、@ Deprecatedで注釈を付けるとコードを削除するつもりであると思われますが、そうではありません。
Jilles van Gurp、

682

回答の多くはHashtableが同期されていると述べていることに注意してください。 実際には、これはほとんどあなたを買いません。 同期はaccessor / mutatorメソッドで行われ、2つのスレッドが同時にマップに追加またはマップから削除するのを停止しますが、実際には、追加の同期が必要になることがよくあります。

非常に一般的なイディオムは「チェックしてから置く」ことです。つまり、でエントリを探し、Mapまだ存在しない場合は追加します。これは、Hashtableまたはを使用するかどうかにかかわらず、アトミック操作ではありませんHashMap

同等の同期HashMapは、次の方法で取得できます。

Collections.synchronizedMap(myMap);

ただし、このロジックを正しく実装するには、フォームの追加の同期が必要です。

synchronized(myMap) {
    if (!myMap.containsKey("tomato"))
        myMap.put("tomato", "red");
}

Hashtableのエントリ(またはHashMapによって取得されたエントリ)を繰り返し処理してCollections.synchronizedMapも、Map追加の同期によって変更されないように保護しない限り、スレッドセーフではありません。

ConcurrentMapインターフェースの実装(たとえばConcurrentHashMap)は、スレッドセーフなチェックナントセマンティクスを含めることにより、この問題の一部を解決します

ConcurrentMap.putIfAbsent(key, value);

53
また、HashMapが変更された場合、それを指すイテレータは無効にレンダリングされることに注意してください。
クリスK

3
したがって、スレッドセーフの点で、synchronized(myMap){...}とConcurrentHashMapの間に違いはありますか?
telebog

3
とても本当です、私は同じことをここで説明しようとしました..lovehasija.com
2012/

@Bhushan:ベストエフォートベースでスローされますが、これは保証された動作ではありません:docs.oracle.com/javase/7/docs/api/java/util/HashMap.html
Matt Stephenson

何年もの間、JVM開発チームの真ん中にいるため、Hashtableの内部同期は、顧客が危険な並行コードを作成するときに、顧客のコードに指を正しく向けるのに少なくとも有用であると言えるでしょう。原因が同時変更である場合、HashMap内の障害(したがって「明らかに」JDK / JVMのバグ)に関するいくつかの苦情を受けました。
Hot Licks、

363

Hashtableレガシーコードと見なされます。Hashtableを使用しHashMapたり派生したりできないことについては何もないHashMapので、新しいコードの場合、に戻る理由はありませんHashtable


101
Hashtable javadoc(強調は追加)から:「Java 2プラットフォームv1.2以降、このクラスはMapインターフェースを実装するように改良され、Java Collections Frameworkのメンバーになりました。」しかし、それはレガシーコードであるとあなたは正しいです。同期のすべての利点は、Collections.synchronizedMap(HashMap)でより効率的に取得できます。(VectorがCollections.synchronizedList(ArrayList)のレガシーバージョンであることと同様)
Kip

15
@ aberrant80:残念ながら、2つの間の選択肢はなく、J2MEのプログラミング時にHashtableを使用する必要があります...
pwes

6
この回答は削除する必要があります。誤った情報が含まれており、多くの賛成票があります。
anon58192932

@ anon58192932質問を編集して修正することは可能ですか?
GC_

1
フラグを立てることによって、ポスター@ aberrant80または管理者の注意を引く必要があります。フラグを立てることは役立つかもしれません-今すぐそれを試みます。
anon58192932

189

この質問は、候補者がコレクションクラスの正しい使用法を理解し、利用可能な代替ソリューションを認識しているかどうかを確認するために、面接でよく尋ねられます。

  1. このHashMapクラスはHashtable、非同期でnullを許可することを除いて、とほぼ同じです。(HashMapnull値をキーと値として許可しますHashtableが、許可しませんnull s)。
  2. HashMap は、マップの順序が長期にわたって一定であることを保証するものではありません。
  3. HashMap一方、非同期されてHashtable同期されます。
  4. のイテレータHashMapはフェイルセーフですが、の列挙子はフェイルセーフではHashtableありませんが、ConcurrentModificationException他のスレッドがIterator独自のremove() メソッド以外の要素を追加または削除してマップを構造的に変更するとスローされます。しかし、これは保証された動作ではなく、JVMによって最善の努力で行われます。

いくつかの重要な用語に関する注意:

  1. 同期とは、一度に1つのスレッドのみがハッシュテーブルを変更できることを意味します。基本的に、それは更新を実行する前のスレッドがHashtable他のユーザーがロックが解放されるのを待つ間オブジェクトのロックを取得する必要が。
  2. フェイルセーフは、反復子のコンテキスト内で関連しています。イテレータがコレクションオブジェクトで作成されていて、他のスレッドがコレクションオブジェクトを「構造的に」変更しようとすると、同時変更例外がスローされます。setコレクションを「構造的に」変更しないため、他のスレッドがメソッドを呼び出すことは可能です。ただし、を呼び出す前にset、コレクションが構造的に変更されているIllegalArgumentException場合はスローされます。
  3. 構造的に変更とは、マップの構造を効果的に変更できる要素を削除または挿入することを意味します。

HashMap によって同期することができます

Map m = Collections.synchronizeMap(hashMap);

マップは、列挙オブジェクトを介した反復を直接サポートする代わりに、コレクションビューを提供します。このセクションで後述するように、コレクションビューはインターフェイスの表現力を大幅に向上させます。マップを使用すると、キー、値、またはキーと値のペアを反復できます。 Hashtable3番目のオプションはありません。Mapは、反復の途中でエントリを削除する安全な方法を提供します。Hashtableしませんでした。最後に、マップはHashtableインターフェースのマイナーな欠陥を修正します。 Hashtableには、containsというメソッドがあります。これは、Hashtablecontainsが指定された値を含む場合にtrueを返し ます。その名前を考えるとHashtable、キーがの主要なアクセスメカニズムであるため、が特定のキーを含んでいる場合、このメソッドはtrueを返すと予想されますHashtable。Mapインターフェースは、メソッドの名前を変更することにより、この混乱の原因を排除します containsValue。また、これによりインターフェースの一貫性が向上します— containsValueパラレルcontainsKey

マップインターフェース


19
この回答には、少なくとも2つの重大な事実上の不正確さが含まれています。それは確かにこれだけの賛成に値するものではありません。
Stephen C

58
1)HashMapの反復子はフェールセーフではありません。彼らはフェイルファストです。これら2つの用語の意味には大きな違いがあります。2)に対するset操作はありませんHashMap。3)以前の変更があった場合、put(...)操作はスローされませんIllegalArgumentException。4)のフェイルファスト動作は、マッピングを変更した場合にHashMap 発生します。5)フェイルファスト動作保証されています。(保証されていないのは、HashTable同時に変更を加えた場合のaの動作です。実際の動作は...予測不可能です。)
Stephen C

25
6)Hashtableは、マップ要素の順序が長期にわたって安定することも保証しません。(あなたはおそらく混乱HashtableしていLinkedHashMapます。)
スティーブンC

4
最近、学生がコレクションの「同期バージョン」を取得することで、複合操作を外部で同期する必要がないという誤った考えを学生が得ることを本当に心配している人はいますか?このビーイングの私のお気に入りの一例thing.set(thing.get() + 1);少なからずいる場合は特に、完全に保護されていないような驚きで初心者をキャッチget()しては、set()メソッドを同期しています。彼らの多くは魔法を期待しています。

HashMapのイテレータはフェールセーフではありません
Abdul

130

HashMapMapハッシュコードを使用して配列のインデックスを作成するインターフェイスの実装。 Hashtable:こんにちは、1998年に呼ばれました。コレクションAPIを元に戻したいと考えています。

真剣にしかし、あなたはHashtable完全に近づかないほうがいいです。シングルスレッドアプリの場合、同期の余分なオーバーヘッドは必要ありません。並行性の高いアプリの場合、偏執的な同期により、飢餓、デッドロック、または不要なガベージコレクションの一時停止が発生する可能性があります。ティム・ハウランドが指摘したように、ConcurrentHashMap代わりに使うかもしれません。


これは実際に理にかなっています。ConcurrentHashMapsは、同期の自由を提供し、デバッグがはるかに簡単になります。
prap19

1
これは、Javaまたはすべてのハッシュマップ実装に固有のものですか。

125

これHashTableは、Java Collections Framework(JCF)が導入される前のレガシークラスであり、後でMapインターフェースを実装するために改良されたことを覚えておいてください。そうだったVectorStack

したがって、他の人が指摘したようにJCFには常により良い代替案があるので、常に新しいコードでそれらから離れてください

以下は、Javaコレクションのチートシートです。灰色のブロックには、従来のクラスHashTable、Vector、Stackが含まれています。

ここに画像の説明を入力してください


72

すでに多くの良い答えが投稿されています。新しい点をいくつか追加して要約します。

HashMapまた、Hashtableどちらもキーと値の形式でデータを格納するために使用されます。どちらもハッシュ技術を使用して一意のキーを格納しています。ただし、以下に示すHashMapクラスとHashtableクラスの間には多くの違いがあります。

HashMap

  1. HashMap同期されていません。これはスレッドセーフではなく、適切な同期コードがないと多くのスレッド間で共有できません。
  2. HashMap 1つのnullキーと複数のnull値を許可します。
  3. HashMap JDK 1.2で導入された新しいクラスです。
  4. HashMap 速いです。
  5. HashMapこのコードを呼び出すことにより、を同期させることができます
    Map m = Collections.synchronizedMap(HashMap);
  6. HashMap イテレーターによってトラバースされます。
  7. のイテレータHashMapはフェイルファストです。
  8. HashMap AbstractMapクラスを継承します。

ハッシュ表

  1. Hashtable同期されます。スレッドセーフであり、多くのスレッドで共有できます。
  2. Hashtable nullキーまたは値は許可されません。
  3. Hashtable レガシークラスです。
  4. Hashtable 遅い。
  5. Hashtable 内部で同期されており、同期を解除することはできません。
  6. Hashtable EnumeratorとIteratorがトラバースします。
  7. の列挙子Hashtableはフェイルファストではありません。
  8. Hashtable 辞書クラスを継承します。

また、読書JavaでのHashMapとHashtableの違いは何ですか?

ここに画像の説明を入力してください


-かなりこの答え(のdupicate)でカバーstackoverflow.com/a/39785829/432903
prayagupd 2017年

なぜ「ハッシュテーブルはレガシークラスです」と言うのですか?そのためのサポートドキュメントはどこにありますか。
IgorGanapolsky 2017年

2
-あなたはこの読むことができる@IgorGanapolsky stackoverflow.com/questions/21086307/...
roottraveller

HashMapの保守は、TreeMapよりもコストがかかります。HashMapが不要な追加バケットを作成するためです。
Abdul

64

izbが言ったことに加えて、HashMapnull値を許可しますが、null値は許可Hashtableしません。

また、Javadocsの状態と同じようにHashtableDictionaryクラスが拡張されているため、インターフェースは置き換えられています。Map


3
しかし、それはHashTableを廃止しませんか?
Pacerier

@Pacerier HashTableはJava 1.7から廃止されました。
Majid Ali Khan、


49

Hashtableに似てHashMapおり、同様のインターフェースを持っています。メソッドが同期さHashMapれるため、レガシーアプリケーションのサポートが必要な場合や同期が必要な場合を除いて、を使用することをお勧めしますHashtables。あなたの場合、マルチスレッドでHashMapsはないので、最善の策です。


36

ハッシュテーブルとハッシュマップのもう1つの重要な違いは、HashMapのイテレータはフェイルファストですが、ハッシュテーブルの列挙子はフェイルファストではなく、他のスレッドがイテレータ自身のremove()メソッド以外の要素を追加または削除することによってマップを構造的に変更すると、ConcurrentModificationExceptionをスローします。しかし、これは保証された動作ではなく、JVMによって最善の努力で行われます。」

私のソース:http : //javarevisited.blogspot.com/2010/10/difference-between-hashmap-and.html


36

ここですでに述べた他のすべての重要な側面に加えて、Collections API(たとえばMapインターフェース)は、Java仕様への「最新かつ最高」の追加に準拠するように常に変更されています。

たとえば、Java 5 Mapの反復を比較します。

for (Elem elem : map.keys()) {
  elem.doSth();
}

古いHashtableアプローチとの比較:

for (Enumeration en = htable.keys(); en.hasMoreElements(); ) {
  Elem elem = (Elem) en.nextElement();
  elem.doSth();
}

Java 1.8では、古き良きスクリプト言語のようにHashMapを作成してアクセスできることも約束されています。

Map<String,Integer> map = { "orange" : 12, "apples" : 15 };
map["apples"];

アップデート:いいえ、彼らは1.8に着陸しません... :(

Project Coinのコレクションの拡張機能はJDK8に含まれる予定ですか?


34

Hashtableは同期されていますが、同期されてHashMapいません。それはHashtableより遅くなりHashmapます。

スレッド化されていないアプリのHashMap場合は、機能的には同じなので、使用します。


30
  • HashTableは同期されます。シングルスレッドで使用している場合は、非同期バージョンであるHashMapを使用できます。非同期オブジェクトは、多くの場合、パフォーマンスが少し向上します。ちなみに、複数のスレッドがHashMapに同時にアクセスし、少なくとも1つのスレッドがマップを構造的に変更する場合、外部で同期する必要があります。Younは、以下を使用して、非同期マップを同期マップにラップできます。

    Map m = Collections.synchronizedMap(new HashMap(...));
  • HashTableには、キーまたは値としてnull以外のオブジェクトのみを含めることができます。HashMapには、1つのnullキーとnull値を含めることができます。

  • Mapによって返されるイテレータはフェイルファストです。イテレータの作成後、マップが構造的にいつでも変更された場合、イテレータ自身のremoveメソッド以外の方法で、イテレータはをスローしConcurrentModificationExceptionます。したがって、同時変更に直面した場合、イテレーターは、将来の未確定の時点で恣意的な非決定論的な動作のリスクを冒すのではなく、迅速かつクリーンに失敗します。一方、Hashtableのキーと要素のメソッドによって返される列挙型はフェイルファストではありません。

  • HashTableとHashMapは、Java Collections Frameworkのメンバーです(Java 2プラットフォームv1.2以降、HashTableはMapインターフェースを実装するために改良されました)。

  • HashTableはレガシーコードと見なされます。ドキュメントでは、スレッドセーフの高度な同時実装が必要な場合は、Hashtableの代わりにConcurrentHashMapを使用することをお勧めしています。

  • HashMapは、要素が返される順序を保証しません。HashTableについても同じだと思いますが、完全にはわかりません。そのことを明確に述べているリソースは見つかりません。


30

HashMapそして、Hashtable同様に重要なアルゴリズムの違いがあります。誰もこれについて以前に言及したことがないので、私がそれを取り上げるのはそのためです。HashMap2つの累乗のサイズのハッシュテーブルを作成し、動的に増加させて、任意のバケットに最大で約8つの要素(衝突)が含まれるようにし、一般的な要素タイプの要素を非常によく攪拌します。ただし、Hashtable実装は、あなたが何をしているのかわかっている場合、ハッシュをよりよく、より細かく制御します。たとえば、値のドメインサイズに最も近い素数を使用してテーブルサイズを修正できます。これにより、HashMapよりもパフォーマンスが向上します。つまり、衝突が少なくなります。場合によっては。

この質問で広く議論されている明らかな違いとは別に、Hashtableはハッシュをより適切に制御できる「手動ドライブ」の車であり、HashMapは一般に良好に機能する「自動ドライブ」の対応物だと思います。


27

ここの情報に基づいて、私はHashMapを使用することをお勧めします。最大の利点は、イテレータを使用しない限り、Javaを反復している間はJavaで変更できないことです。


5
実際にはそれを防止するのではなく、それを検出してエラーをスローするだけです。
Bart van Heukelom、2010

1
基になるコレクションが変更される前にConncurrentModificationExceptionをスローすると確信していますが、間違っている可能性もあります。
pkaeding

それはなります試み同時変更を検出し、例外をスローします。しかし、スレッドで何かをしている場合、それは何の約束もできません。破損など、絶対に何でも起こります。
cHao

24

Collectionコンテナとも呼ばれる)は、単に複数の要素を1つの単位にグループ化するオブジェクトです。Collectionは、集計データの保存、取得、操作、通信に使用されます。コレクションフレームワークWは、を表現および操作するための統合アーキテクチャです。

HashMap JDK1.2そしてハッシュテーブルはJDK1.0、両方ともに表されているオブジェクトのグループ表すために使用されている<Key, Value>ペアを。各<Key, Value>ペアはEntryオブジェクトと呼ばれます。エントリのコレクションは、HashMapおよびのオブジェクトによって参照されますHashtable。コレクション内のキーは、一意または固有である必要があります。[マップされた値、特定のキーを取得するために使用されるため。コレクション内の値は複製できます。]


« スーパークラス、レガシー、コレクションフレームワークメンバー

Hashtableは、で導入されたレガシークラスでありJDK1.0、Dictionaryクラスのサブクラスです。From JDK1.2Hashtableは、Mapインターフェースを実装してコレクションフレームワークのメンバーを作成するように再設計されています。HashMapは、Java Collection Frameworkの導入当初からメンバーですJDK1.2。HashMapは、AbstractMapクラスのサブクラスです。

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

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

« 初期容量と負荷係数

容量はハッシュテーブル内のバケット数であり、初期容量はハッシュテーブルが作成されたときの容量です。ハッシュテーブルが開いていることに注意してください。hashcollision」の場合、単一のバケットに複数のエントリが格納されます。これらのエントリは順次検索する必要があります。負荷係数は、ハッシュテーブルの容量が自動的に増加する前に、ハッシュテーブルがどの程度いっぱいになるかを示す尺度です。

HashMapは、デフォルトの初期容量(16)とデフォルトの負荷係数(0.75)で空のハッシュテーブルを作成します。Hashtableはデフォルトの初期容量(11)と負荷係数/充填率(0.75)で空のハッシュテーブルを作成します。

ハッシュマップとハッシュテーブル

« ハッシュ衝突の場合の構造変更

HashMapHashtableハッシュの衝突の場合、マップエントリをリンクリストに格納します。Java8からHashMap、ハッシュバケットが特定のしきい値を超えた場合、そのバケットはから切り替わりlinked list of entries to a balanced treeます。最悪の場合のパフォーマンスをO(n)からO(log n)に改善します。リストをバイナリツリーに変換するとき、ハッシュコードは分岐変数として使用されます。同じバケットに2つの異なるハッシュコードがある場合、1つはより大きく、ツリーの右側に移動し、もう1つは左側に移動すると見なされます。しかし、両方のハッシュコードが等しく、 多くてもJava 8 SRCの場合、stackpostHashMapは、キーが比較可能であると想定し、キーを比較して方向を決定することで、順序を維持できるようにします。HashMap 同等のキーを作成することをお勧めします。バケットサイズが到達した場合のエントリの追加についてTREEIFY_THRESHOLD = 8エントリのリンクリストをバランスツリーに変換します。バランスツリーを下回って最大エントリを削除するリンクツリーがエントリのリンクリストに再変換されます。TREEIFY_THRESHOLDUNTREEIFY_THRESHOLD = 6

« コレクションビューの反復、Fail-FastおよびFail-Safe

    +--------------------+-----------+-------------+
    |                    | Iterator  | Enumeration |
    +--------------------+-----------+-------------+
    | Hashtable          | fail-fast |    safe     |
    +--------------------+-----------+-------------+
    | HashMap            | fail-fast | fail-fast   |
    +--------------------+-----------+-------------+
    | ConcurrentHashMap  |   safe    |   safe      |
    +--------------------+-----------+-------------+

Iterator本質的にフェイルファストです。つまり、独自のremove()メソッド以外の反復中にコレクションが変更されると、ConcurrentModificationExceptionがスローされます。どこEnumerationフェイルセーフな性質です。反復中にコレクションが変更されても、例外はスローされません。

Java APIドキュメントによると、イテレータは常に列挙よりも優先されます。

注意: Enumerationインターフェースの機能は、Iteratorインターフェースと同じです。さらに、Iteratorはオプションの削除操作を追加し、メソッド名が短くなっています。新しい実装では、列挙よりもイテレータの使用を検討する必要があります。

Java 5のConcurrentMapインタフェースを導入しましたConcurrentHashMap-非常に同時、高性能なConcurrentMap実装では、ハッシュテーブルに裏打ちされました。この実装は、取得を実行するときに決してブロックせず、クライアントが更新の同時実行レベルを選択できるようにします。これは、のドロップイン置換として意図されています。のHashtable実装に加えてConcurrentMap、に固有の「レガシー」メソッドのすべてをサポートしHashtableます。

  • HashMapEntrys値は揮発性であるため、競合する変更と後続の読み取りに対して細粒度の一貫性が保証されます。各読み取りは、最後に完了した更新を反映しています

  • イテレータと列挙型はフェイルセーフです-イテレータ/列挙型の作成以降のある時点での状態を反映しています。これにより、一貫性が低下しますが、読み取りと変更を同時に行うことができます。ConcurrentModificationExceptionはスローされません。ただし、イテレータは一度に1つのスレッドのみが使用するように設計されています。

  • Hashtableは異なりHashMap、このクラスではnullをキーまたは値として使用することはできません。

public static void main(String[] args) {

    //HashMap<String, Integer> hash = new HashMap<String, Integer>();
    Hashtable<String, Integer> hash = new Hashtable<String, Integer>();
    //ConcurrentHashMap<String, Integer> hash = new ConcurrentHashMap<>();

    new Thread() {
        @Override public void run() {
            try {
                for (int i = 10; i < 20; i++) {
                    sleepThread(1);
                    System.out.println("T1 :- Key"+i);
                    hash.put("Key"+i, i);
                }
                System.out.println( System.identityHashCode( hash ) );
            } catch ( Exception e ) {
                e.printStackTrace();
            }
        }
    }.start();
    new Thread() {
        @Override public void run() {
            try {
                sleepThread(5);
                // ConcurrentHashMap  traverse using Iterator, Enumeration is Fail-Safe.

                // Hashtable traverse using Enumeration is Fail-Safe, Iterator is Fail-Fast.
                for (Enumeration<String> e = hash.keys(); e.hasMoreElements(); ) {
                    sleepThread(1);
                    System.out.println("T2 : "+ e.nextElement());
                }

                // HashMap traverse using Iterator, Enumeration is Fail-Fast.
                /*
                for (Iterator< Entry<String, Integer> > it = hash.entrySet().iterator(); it.hasNext(); ) {
                    sleepThread(1);
                    System.out.println("T2 : "+ it.next());
                    // ConcurrentModificationException at java.util.Hashtable$Enumerator.next
                }
                */

                /*
                Set< Entry<String, Integer> > entrySet = hash.entrySet();
                Iterator< Entry<String, Integer> > it = entrySet.iterator();
                Enumeration<Entry<String, Integer>> entryEnumeration = Collections.enumeration( entrySet );
                while( entryEnumeration.hasMoreElements() ) {
                    sleepThread(1);
                    Entry<String, Integer> nextElement = entryEnumeration.nextElement();
                    System.out.println("T2 : "+ nextElement.getKey() +" : "+ nextElement.getValue() );
                    //java.util.ConcurrentModificationException at java.util.HashMap$HashIterator.nextNode
                    //                                          at java.util.HashMap$EntryIterator.next
                    //                                          at java.util.Collections$3.nextElement
                }
                */
            } catch ( Exception e ) {
                e.printStackTrace();
            }
        }
    }.start();

    Map<String, String> unmodifiableMap = Collections.unmodifiableMap( map );
    try {
        unmodifiableMap.put("key4", "unmodifiableMap");
    } catch (java.lang.UnsupportedOperationException e) {
        System.err.println("UnsupportedOperationException : "+ e.getMessage() );
    }
}
static void sleepThread( int sec ) {
    try {
        Thread.sleep( 1000 * sec );
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

« NullキーとNull値

HashMap最大1つのnullキーと任意の数のnull値を許可します。Hashtablenullが1つでもnull値も許可されない場合、キーまたは値がnullの場合、NullPointerExceptionがスローされます。

« 同期、スレッドセーフ

Hashtable内部で同期されます。したがって、Hashtableマルチスレッドアプリケーションで使用しても非常に安全です。as HashMapは内部的に同期されていません。したがって、HashMap外部同期のないマルチスレッドアプリケーションで使用するのは安全ではありません。メソッドHashMapを使用して外部同期できCollections.synchronizedMap()ます。

« パフォーマンス

Hashtable内部的に同期され、これは作るHashtable少しより遅いですHashMap


@見る


18

スレッド化されたアプリの場合、パフォーマンス要件に応じて、ConcurrentHashMapを使いこなすことがよくあります。


17

1. HashmapおよびHashTable店舗のキーと値の両方。

2. Hashmapとして1つのキーを保存できますnullHashtable保存できませんnull

3. HashMap同期されていませんがHashtable、同期されています。

4. HashMapと同期することができますCollection.SyncronizedMap(map)

Map hashmap = new HashMap();

Map map = Collections.SyncronizedMap(hashmap);

16

すでに述べた違いは別として、Java 8以降HashMap、各バケットで使用されるノード(リンクされたリスト)を動的にTreeNodes(赤黒ツリー)に置き換えるため、高いハッシュ衝突が存在する場合でも、最悪の場合は検索

Oのための(ログ(N))HashMap 中のO(N) Hashtable

*上記の改善が適用されていないHashtable、まだ、だけにHashMapLinkedHashMapと、ConcurrentHashMap

FYI、現在、

  • TREEIFY_THRESHOLD = 8 :バケットに8つを超えるノードが含まれる場合、リンクリストはバランスの取れたツリーに変換されます。
  • UNTREEIFY_THRESHOLD = 6 :バケットが小さくなった場合(削除またはサイズ変更により)、ツリーはリンクリストに変換されます。

14

HashTableとHashMapsには5つの基本的な違いがあります。

  1. マップを使用すると、キー、値、および両方のキーと値のペアを反復して取得することもできます。HashTableにはこの機能のすべてがありません。
  2. Hashtableには、contains()関数があり、使用するのが非常に混乱しています。包含の意味が少しずれているためです。キーを含むか値を含むか?理解するのは難しい。マップには、ContainsKey()関数とContainsValue()関数があり、非常に簡単に理解できます。
  3. ハッシュマップでは、反復しながら要素を安全に削除できます。ハッシュテーブルでは不可能です。
  4. HashTableはデフォルトで同期されるため、複数のスレッドで簡単に使用できます。HashMapはデフォルトでは同期されないため、単一スレッドでのみ使用できます。ただし、Collections utilクラスのsynchronizedMap(Map m)関数を使用して、HashMapを同期に変換できます。
  5. HashTableはnullキーまたはnull値を許可しません。HashMapは1つのnullキーと複数のnull値を許可します。

13

私の小さな貢献:

  1. 最初との間で最も重要な異なるHashtableとはHashMap、ということですHashMapスレッドセーフではありませんががHashtable、スレッドセーフなコレクションです。

  2. との2つ目の重要な違いはパフォーマンスです。同期されていないのでHashtableHashMapはパフォーマンスHashMapが向上しHashtableます。

  3. Hashtablevsの3番目の違いHashMapは、Hashtable古いクラスであり、JavaのConcurrentHashMap代わりに使用する必要があることですHashtable


11

HashMap:java.utilパッケージ内で使用可能なクラスであり、要素をキーと値の形式で格納するために使用されます。

ハッシュテーブル:コレクションフレームワーク内で認識されているレガシークラスです。


もしそうなら、それは答えとしてではなくコメントの中にあるべきです。
マニカントゴータム

10

HashTableはjdkのレガシークラスであり、今後は使用しないでください。使用法をConcurrentHashMapに置き換えます。スレッドセーフを必要としない場合は、スレッドセーフではありませんが高速でメモリ使用量が少ないHashMapを使用してください。


当時、私は他の答えを考えていたので、HashTableは却下せず、スレッドセーフであると説明しました。真実は、コードにHashTableが表示されたらすぐに、ビートをスキップせずにConcurrentHashMapに置き換える必要があるということです。スレッドの安全性が問題にならない場合は、HashMapを使用してパフォーマンスを少し向上させることができます。
jontejj 2015

10
  1. Hashtableは同期されてHashMapいますが、同期されていません。
  2. もう1つの違いはHashMap、の列挙子がフェイルセーフであるのに対し、のイテレーターはフェイルセーフでHashtableあることです。反復中にマップを変更すると、わかります。
  3. HashMapヌル値を許可しますが、許可しHashtableません。

3
HashMapイテレータはフェイルセーフではなくフェイルファストです。そのため、反復中に変更を許可するConcurrentHashMapがあります。この投稿をチェックしてくださいjournaldev.com/122/…–
Pankaj

9

HashMapとHashTable

  • HashMapとHashTableに関するいくつかの重要なポイント。詳細は以下をお読みください。

1)HashtableとHashmapはjava.util.Mapインターフェースを実装します2)HashmapとHashtableはどちらもハッシュベースのコレクションです。そしてハッシュに取り組んでいます。したがって、これらはHashMapとHashTableの類似点です。

  • HashMapとHashTableの違いは何ですか?

1)最初の違いは、HashMapはスレッドセーフではないが、HashTable
はスレッドセーフではないことです。2)HashMapはスレッドセーフではないため、パフォーマンスの面で優れています。一方、Hashtableのパフォーマンスはスレッドセーフであるため、賢明ではありません。したがって、複数のスレッドがHashtableに同時にアクセスすることはできません。


2
この回答はいくつかの点で正しくないため、反対票が投じられました。HashtableはMapインターフェースを実装していませんが、廃止されたDictionaryクラスのみを拡張しています。
Yannis Sermetziadis 2017年

8

Hashtable:

ハッシュテーブルは、キーと値のペアの値を保持するデータ構造です。キーと値の両方にnullは許可されません。NullPointerExceptionnull値を追加すると、が取得されます。同期されます。したがって、それにはコストが伴います。特定の時間に1つのスレッドのみがHashTableにアクセスできます。

import java.util.Map;
import java.util.Hashtable;

public class TestClass {

    public static void main(String args[ ]) {
    Map<Integer,String> states= new Hashtable<Integer,String>();
    states.put(1, "INDIA");
    states.put(2, "USA");

    states.put(3, null);    //will throw NullPointerEcxeption at runtime

    System.out.println(states.get(1));
    System.out.println(states.get(2));
//  System.out.println(states.get(3));

    }
}

HashMap:

HashMapHashtableに似ていますが、キーと値のペアも受け入れます。キーと値の両方にnullを許可します。HashTableそれがそうであるので、その性能はより良いですunsynchronized

例:

import java.util.HashMap;
import java.util.Map;

public class TestClass {

    public static void main(String args[ ]) {
    Map<Integer,String> states = new HashMap<Integer,String>();
    states.put(1, "INDIA");
    states.put(2, "USA");

    states.put(3, null);    // Okay
    states.put(null,"UK");

    System.out.println(states.get(1));
    System.out.println(states.get(2));
    System.out.println(states.get(3));

    }
}

5

HashMapはエミュレートされているので使用できますがGWT client code、そうでHashtableはありません。


それは2つのAPIの違いの包括的な説明ですか?
IgorGanapolsky 2017年

はい(シック!)。GWT開発者が知っておくべきことはこれだけです。
ピンポン

5

古くて古典的なトピックですが、これを説明するこの役立つブログを追加したいだけです。

http://blog.manishchhabra.com/2012/08/the-5-main-differences-betwen-hashmap-and-hashtable/

Manish Chhabraによるブログ

HashMapとHashtableの5つの主な違い

HashMapとHashtableはどちらもjava.util.Mapインターフェースを実装していますが、より効率的なコードを書くためにJava開発者が理解しなければならないいくつかの違いがあります。Java 2プラットフォームv1.2以降、HashtableクラスはMapインターフェイスを実装するように改良され、Javaコレクションフレームワークのメンバーになりました。

  1. HashMapとHashtableの主な違いの1つは、HashMapが非同期であるのに対し、Hashtableは同期されていることです。つまり、Hashtableはスレッドセーフであり、複数のスレッド間で共有できますが、適切な同期がないとHashMapを複数のスレッド間で共有できません。Java 5は、Hashtableの代替であり、JavaのHashtableよりも優れたスケーラビリティを提供するConcurrentHashMapを導入しました。同期とは、一度に1つのスレッドのみがハッシュテーブルを変更できることを意味します。基本的には、ハッシュテーブルで更新を実行する前にスレッドがオブジェクトのロックを取得する必要がある一方で、他のスレッドはロックが解放されるのを待つことを意味します。

  2. HashMapクラスは、nullを許可することを除いて、Hashtableとほぼ同じです。(HashMapではnull値をキーと値として使用できますが、Hashtableではnullを使用できません)。

  3. HashMapとHashtableの3番目の重要な違いは、HashMapのイテレーターがフェイルファストイテレーターであるのに対し、Hashtableの列挙子はそうではなく、他のスレッドがイテレーター自身のremove( ) 方法。しかし、これは保証された動作ではなく、最善の努力でJVMによって実行されます。これは、Javaの列挙とイテレータの重要な違いでもあります。

  4. HashtableとHashMapのもう1つの注目すべき違いは、スレッドセーフと同期のため、シングルスレッド環境で使用した場合、HashtableはHashMapよりもはるかに遅いということです。したがって、同期が必要なく、HashMapが1つのスレッドでのみ使用されている場合は、JavaでHashtableを実行します。

  5. HashMapは、マップの順序が長期にわたって一定であることを保証しません。

HashMapは、

Map m = Collections.synchronizedMap(hashMap);

要約すると、JavaのHashtableとHashMapの間には大きな違いがあります。たとえば、スレッドの安全性と速度などであり、スレッドの安全性が絶対に必要な場合にのみHashtableを使用します。Java5を実行している場合は、JavaでConcurrentHashMapの使用を検討してください。


ConcurrentHashMapは読み取り同期されませんが、Hashtableは同期されます。したがって、書き込みと同時に発生する大量の読み取り操作がある場合、データの整合性を重視する場合はHashtableの方が適しています。
IgorGanapolsky 2017年

5

HashMapHashtableはどちらも、キーと値の形式でデータを格納するために使用されます。どちらもハッシュ技術を使用して一意のキーを格納しています。ただし、以下に示すHashMapクラスとHashtableクラスの間には多くの違いがあります。

ここに画像の説明を入力してください


素敵なビジュアルまとめ!
Nadjib Mami
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.