web-dev-qa-db-ja.com

C#ではHashtableよりもDictionaryが優先されるのはなぜですか。

ほとんどのプログラミング言語では、辞書はハッシュテーブルよりも好まれています。その理由は何ですか?

1301
Nakul Chaudhary

それが価値があるもののために、Dictionary(概念的に)ハッシュテーブルです。

「なぜHashtableクラスの代わりにDictionary<TKey, TValue>クラスを使うのですか?」という意味であれば、それは簡単な答えです。Dictionary<TKey, TValue>はジェネリック型ですが、Hashtableはそうではありません。これはDictionary<TKey, TValue>で型の安全性が得られることを意味します。ランダムなオブジェクトを挿入することはできず、取り出した値をキャストする必要もないからです。

興味深いことに、.NET FrameworkのDictionary<TKey, TValue>実装は、ソースコードのこのコメントからわかるように、Hashtableに基づいています。

総称辞書はHashtableの情報源からコピーされた

出典

1495
Michael Madsen

Dictionary<<< >>>Hashtable違い:

  • 一般 <<< >>> 非一般
  • 独自のスレッド同期が必要 <<< >>> スレッドセーフ version throughSynchronized()method
  • 列挙型アイテム:KeyValuePair<<< >>>列挙型アイテム:DictionaryEntry
  • 新しい(> .NET 2.0 )<<< >>>古い( .NET 1.0 以降)
  • System.Collections.Generic <<< >>>にあります System.Collections
  • 存在しないキーへのリクエスト 例外をスローします <<< >>>存在しないキーへのリクエスト nullを返します
  • 潜在的に少し 値型のためのより速い <<< >>> もう少し遅い (値のタイプのためのボクシング/ボックス化解除が必要)

Dictionary/Hashtable類似点:

  • 両方とも内部的に ハッシュテーブル ==キーに従った多項目データへの高速アクセス
  • 両方とも 不変でユニークなキーを必要とする
  • 両方のキーには独自のGetHashCode()methodが必要です

同じような .NETコレクション(DictionaryとHashtableの代わりに使用する候補):

  • ConcurrentDictionary - スレッドセーフ (同時に複数のスレッドから安全にアクセス可能)
  • HybridDictionary - 最適化されたパフォーマンス (少数のアイテムに対しても多数のアイテムに対しても)
  • OrderedDictionary - 値は int index を介してアクセスできます(項目が追加された順に)
  • SortedDictionary - items 自動ソート
  • StringDictionary - 強く型付けされた/ 文字列用に最適化された
596
Thetam

なぜならDictionaryはジェネリッククラス(Dictionary<TKey, TValue>)なので、その内容へのアクセスは型保証されているからです(つまり、Objectから行うようにHashtableからキャストする必要はありません)。

比較する

var customers = new Dictionary<string, Customer>();
...
Customer customer = customers["ALi G"];

var customers = new Hashtable();
...
Customer customer = customers["ALi G"] as Customer;

ただし、Dictionaryは内部的にハッシュテーブルとして実装されているので、技術的には同じように機能します。

173
gius

参考:.NETでは、Hashtableは複数のリーダースレッドと単一の書き込みスレッドで使用できるスレッドセーフであり、Dictionaryではpublic staticメンバーはスレッドセーフですが、インスタンスメンバーはスレッドセーフであるとは限りません。

このため、すべての辞書をHashtableに戻す必要がありました。

84
user38902

.NETでは、Dictionary<,>HashTableの違いは、主に前者がジェネリック型であるということです。したがって、静的型チェック(およびボクシングの削減)という点で総称のすべての利点が得られます。パフォーマンスの面で考える - ボクシングには確かなメモリコストがあります、しかし)。

67
Marc Gravell

人々は辞書はハッシュテーブルと同じであると言っています。

これは必ずしも真実ではありません。ハッシュテーブルは 実装 辞書への1つの方法です。典型的なもので、それはDictionaryクラスの.NETのデフォルトのものかもしれませんが、定義上それだけではありません。

リンクリストまたは検索ツリーを使用して辞書を同様に実装することもできますが、それほど効率的ではありません(効率的な指標として)。

32
rix0rrr

CollectionsGenericsは、オブジェクトのグループを処理するのに役立ちます。 .NETでは、すべてのコレクションオブジェクトはIEnumerableインターフェースの下に置かれ、そのインターフェースはArrayList(Index-Value))HashTable(Key-Value)を持ちます。 .NET Framework 2.0以降、ArrayListHashTableListDictionaryに置き換えられました。 ArraylistHashTableは今日のプロジェクトではもう使われていません。

HashTableDictionaryの違いによると、Dictionaryは総称で、Hastableは総称ではありません。任意の型のオブジェクトをHashTableに追加することができますが、取得する際には、それを必要な型にキャストする必要があります。だから、それはタイプセーフではありません。しかしdictionaryには、それ自身を宣言しながらキーと値の型を指定できるので、検索中にキャストする必要はありません。

例を見てみましょう。

ハッシュ表

class HashTableProgram
{
    static void Main(string[] args)
    {
        Hashtable ht = new Hashtable();
        ht.Add(1, "One");
        ht.Add(2, "Two");
        ht.Add(3, "Three");
        foreach (DictionaryEntry de in ht)
        {
            int Key = (int)de.Key; //Casting
            string value = de.Value.ToString(); //Casting
            Console.WriteLine(Key + " " + value);
        }

    }
}

辞書、

class DictionaryProgram
{
    static void Main(string[] args)
    {
        Dictionary<int, string> dt = new Dictionary<int, string>();
        dt.Add(1, "One");
        dt.Add(2, "Two");
        dt.Add(3, "Three");
        foreach (KeyValuePair<int, String> kv in dt)
        {
            Console.WriteLine(kv.Key + " " + kv.Value);
        }
    }
}
22
Sujit

辞書:

  • 存在しないキーを見つけようとすると、Exceptionを返す/スローします。

  • ボクシングとアンボクシングがないので、Hashtableより速いです。

  • スレッドセーフなのはパブリック静的メンバーだけです。

  • ディクショナリはジェネリック型なので、任意のデータ型で使用できます(作成時には、キーと値の両方にデータ型を指定する必要があります)。

    例:Dictionary<string, string> <NameOfDictionaryVar> = new Dictionary<string, string>();

  • 辞書はHashtableの型保証された実装で、KeysValuesは強く型付けされています。

ハッシュ表:

  • 存在しないキーを見つけようとするとnullを返します。

  • ボクシングとアンボクシングが必要なので、辞書より遅くなります。

  • Hashtableのすべてのメンバーはスレッドセーフです。

  • Hashtableはジェネリック型ではありません、

  • Hashtableは緩やかに型付けされたデータ構造です。私たちはどんな型のキーと値も追加することができます。

16
Altaf Patel

MSDNの C#を使用したデータ構造の広範な検査 の記事では、 衝突解決方法 にも違いがあると述べています。

Hashtableクラスは rehashing と呼ばれる手法を使います。

再ハッシュは次のように機能します。ハッシュの異なる関数の集合があります。1 ... Hnハッシュテーブルからアイテムを挿入または取得するとき、最初はH1 ハッシュ関数が使用されています。これが衝突につながるならば、H2 代わりに試され、H以降n 必要に応じて。

辞書は chaining と呼ばれるテクニックを使います。

再ハッシュでは、衝突が発生した場合にハッシュが再計算され、ハッシュに対応する新しいスロットが試されます。しかし連鎖では、 衝突を保持するために2次データ構造が利用されます 。具体的には、ディクショナリ内の各スロットには、そのバケットにマップされる要素の配列があります。衝突が発生した場合、衝突している要素がバケットのリストの先頭に追加されます。

15
alexandrekow

.NET Framework 3.5以降、 HashSet<T> もあります。これは、キーのみが必要で値が不要な場合は、 Dictionary<TKey, TValue> の長所をすべて提供します。

そのため、Dictionary<MyType, object>を使用し、常にタイプセーフハッシュテーブルをシミュレートするために値をnullに設定する場合は、おそらく HashSet<T> に切り替えることを検討する必要があります。

14
Oliver

Hashtableはゆるやかに型付けされたデータ構造なので、Hashtableに任意の型のキーと値を追加できます。 Dictionaryクラスは型保証されたHashtableの実装で、キーと値は強く型付けされています。 Dictionaryインスタンスを作成するときは、キーと値の両方にデータ型を指定する必要があります。

12
flesh

MSDNが言うことに注意してください: "Dictionary <(Of <(TKey、TValue>)>)クラスは ハッシュ表Dictionary <(Of <(TKey、TValue>)>)クラスの "、not"は、 ハッシュ表

辞書はHashTableとしては実装されていませんが、ハッシュテーブルの概念に従って実装されています。 Genericsを使用しているため、この実装はHashTableクラスとは無関係ですが、Microsoftは内部的に同じコードを使用し、Object型のシンボルをTKeyとTValueに置き換えることができました。

.NET 1.0にはジェネリックは存在しませんでした。 HashTableとArrayListが最初に始まった場所です。

11
Brant

ハッシュ表:

キー/値はヒープに格納されている間、オブジェクト(ボクシング)型に変換されます。

キー/値は、ヒープから読み取る際に目的の型に変換する必要があります。

これらの操作は非常に費用がかかります。ボクシング/ボクシング解除をできるだけ避ける必要があります。

辞書: / HashTableの一般的な変種。

ボクシングはありません。変換は不要です。

Hashtableオブジェクトは、コレクションの要素を含むバケットから構成されています。バケットはHashtable内の要素の仮想サブグループ、 です。これにより、ほとんどのコレクション よりも検索と検索が容易かつ迅速になります。

DictionaryクラスはHashtableクラスと同じ機能を持ちます。 Hashtableの要素はObject型であるため、値を格納または取得する場合は通常ボクシングおよびアンボックス化が行われるため、特定の型のディクショナリ(Object以外) はHashtable よりも値型に対してパフォーマンスが高くなりますタイプ。

さらに読むために: ハッシュテーブルと辞書のコレクション型

8
mparkuk

私が理解できるもう一つの違いは:

WebサービスではDictionary <KT、VT>(総称)を使用することはできません。その理由は、Webサービス標準が総称標準をサポートしていないためです。

6
prashant

Dictionary<>はジェネリック型なので、型安全です。

HashTableには任意の値型を挿入できます。これにより、例外が発生することがあります。しかしDictionary<int>は整数値のみを受け付け、同様にDictionary<string>は文字列のみを受け付けます。

そのため、HashTableではなくDictionary<>を使用することをお勧めします。

6
Kishore Kumar

もう1つの重要な違いは、Hashtableがスレッドセーフであるということです。 Hashtableには、マルチリーダー/シングルライター(MR/SW)スレッドセーフティが組み込まれています。つまり、Hashtableは1つのライターを複数のリーダーと一緒にロックすることなくロックできます。

Dictionaryの場合、スレッドセーフはありません。スレッドセーフが必要な場合は、独自の同期を実装する必要があります。

さらに詳しく説明すると:

Hashtableは、コレクションを囲むスレッドセーフなラッパーを返すSynchronizedプロパティを通じて、スレッドセーフを提供します。ラッパーは、追加または削除操作のたびにコレクション全体をロックすることによって機能します。したがって、コレクションにアクセスしようとしている各スレッドは、順番が1つロックされるのを待つ必要があります。これはスケーラブルではなく、大規模コレクションではパフォーマンスが大幅に低下する可能性があります。また、デザインは競合状態から完全に保護されていません。

List<T>, Dictionary<TKey, TValue>などの.NET Framework 2.0コレクションクラスはスレッド同期を提供しません。項目が複数のスレッドで同時に追加または削除された場合、ユーザーコードはすべての同期を提供する必要があります。

型の安全性とスレッドの安全性が必要な場合は、.NET Frameworkのコンカレントコレクションクラスを使用してください。さらに読む ここ

もう1つの違いは、Dictionaryに複数のエントリを追加しても、エントリが追加された順序が維持されることです。 Dictionaryからアイテムを取得すると、それらを挿入したのと同じ順序でレコードが取得されます。 Hashtableは挿入順を保持しませんが。

6
NullReference

ほとんどのプログラミング言語では、辞書はハッシュテーブルよりも好まれています。

私はこれが必ずしも正しいとは思わない、彼らが好む 用語に依存して、ほとんどの言語はどちらか一方を持っている

しかし、C#では、(私にとって)明らかな理由は、C#HashTablesとSystem.Collections名前空間の他のメンバーがほとんど使われていないことです。それらはc#V1.1にありました。それらはC#2.0からSystem.Collections.Generic名前空間のGenericクラスに置き換えられました。

0
kristianp