ほとんどのプログラミング言語では、辞書はハッシュテーブルよりも好まれています。その理由は何ですか?
それが価値があるもののために、Dictionary は (概念的に)ハッシュテーブルです。
「なぜHashtable
クラスの代わりにDictionary<TKey, TValue>
クラスを使うのですか?」という意味であれば、それは簡単な答えです。Dictionary<TKey, TValue>
はジェネリック型ですが、Hashtable
はそうではありません。これはDictionary<TKey, TValue>
で型の安全性が得られることを意味します。ランダムなオブジェクトを挿入することはできず、取り出した値をキャストする必要もないからです。
興味深いことに、.NET FrameworkのDictionary<TKey, TValue>
実装は、ソースコードのこのコメントからわかるように、Hashtable
に基づいています。
総称辞書はHashtableの情報源からコピーされた
Dictionary
<<< >>>Hashtable
違い:
Synchronized()
methodKeyValuePair
<<< >>>列挙型アイテム:DictionaryEntry
Dictionary
/Hashtable
類似点:
GetHashCode()
methodが必要です同じような .NETコレクション(DictionaryとHashtableの代わりに使用する候補):
ConcurrentDictionary
- スレッドセーフ (同時に複数のスレッドから安全にアクセス可能)HybridDictionary
- 最適化されたパフォーマンス (少数のアイテムに対しても多数のアイテムに対しても)OrderedDictionary
- 値は int index を介してアクセスできます(項目が追加された順に)SortedDictionary
- items 自動ソート StringDictionary
- 強く型付けされた/ 文字列用に最適化された なぜなら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
は内部的にハッシュテーブルとして実装されているので、技術的には同じように機能します。
参考:.NETでは、Hashtable
は複数のリーダースレッドと単一の書き込みスレッドで使用できるスレッドセーフであり、Dictionary
ではpublic staticメンバーはスレッドセーフですが、インスタンスメンバーはスレッドセーフであるとは限りません。
このため、すべての辞書をHashtable
に戻す必要がありました。
.NETでは、Dictionary<,>
とHashTable
の違いは、主に前者がジェネリック型であるということです。したがって、静的型チェック(およびボクシングの削減)という点で総称のすべての利点が得られます。パフォーマンスの面で考える - ボクシングには確かなメモリコストがあります、しかし)。
人々は辞書はハッシュテーブルと同じであると言っています。
これは必ずしも真実ではありません。ハッシュテーブルは 実装 辞書への1つの方法です。典型的なもので、それはDictionary
クラスの.NETのデフォルトのものかもしれませんが、定義上それだけではありません。
リンクリストまたは検索ツリーを使用して辞書を同様に実装することもできますが、それほど効率的ではありません(効率的な指標として)。
Collections
とGenerics
は、オブジェクトのグループを処理するのに役立ちます。 .NETでは、すべてのコレクションオブジェクトはIEnumerable
インターフェースの下に置かれ、そのインターフェースはArrayList(Index-Value))
&HashTable(Key-Value)
を持ちます。 .NET Framework 2.0以降、ArrayList
とHashTable
はList
とDictionary
に置き換えられました。 Arraylist
とHashTable
は今日のプロジェクトではもう使われていません。
HashTable
とDictionary
の違いによると、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);
}
}
}
辞書:
存在しないキーを見つけようとすると、Exceptionを返す/スローします。
ボクシングとアンボクシングがないので、Hashtableより速いです。
スレッドセーフなのはパブリック静的メンバーだけです。
ディクショナリはジェネリック型なので、任意のデータ型で使用できます(作成時には、キーと値の両方にデータ型を指定する必要があります)。
例:Dictionary<string, string> <NameOfDictionaryVar> = new Dictionary<string, string>();
辞書はHashtableの型保証された実装で、Keys
とValues
は強く型付けされています。
ハッシュ表:
存在しないキーを見つけようとするとnullを返します。
ボクシングとアンボクシングが必要なので、辞書より遅くなります。
Hashtableのすべてのメンバーはスレッドセーフです。
Hashtableはジェネリック型ではありません、
Hashtableは緩やかに型付けされたデータ構造です。私たちはどんな型のキーと値も追加することができます。
MSDNの C#を使用したデータ構造の広範な検査 の記事では、 衝突解決方法 にも違いがあると述べています。
Hashtableクラスは rehashing と呼ばれる手法を使います。
再ハッシュは次のように機能します。ハッシュの異なる関数の集合があります。1 ... Hnハッシュテーブルからアイテムを挿入または取得するとき、最初はH1 ハッシュ関数が使用されています。これが衝突につながるならば、H2 代わりに試され、H以降n 必要に応じて。
辞書は chaining と呼ばれるテクニックを使います。
再ハッシュでは、衝突が発生した場合にハッシュが再計算され、ハッシュに対応する新しいスロットが試されます。しかし連鎖では、 衝突を保持するために2次データ構造が利用されます 。具体的には、ディクショナリ内の各スロットには、そのバケットにマップされる要素の配列があります。衝突が発生した場合、衝突している要素がバケットのリストの先頭に追加されます。
.NET Framework 3.5以降、 HashSet<T>
もあります。これは、キーのみが必要で値が不要な場合は、 Dictionary<TKey, TValue>
の長所をすべて提供します。
そのため、Dictionary<MyType, object>
を使用し、常にタイプセーフハッシュテーブルをシミュレートするために値をnull
に設定する場合は、おそらく HashSet<T>
に切り替えることを検討する必要があります。
Hashtable
はゆるやかに型付けされたデータ構造なので、Hashtable
に任意の型のキーと値を追加できます。 Dictionary
クラスは型保証されたHashtable
の実装で、キーと値は強く型付けされています。 Dictionary
インスタンスを作成するときは、キーと値の両方にデータ型を指定する必要があります。
MSDNが言うことに注意してください: "Dictionary <(Of <(TKey、TValue>)>)クラスは ハッシュ表Dictionary <(Of <(TKey、TValue>)>)クラスの "、not"は、 ハッシュ表「
辞書はHashTableとしては実装されていませんが、ハッシュテーブルの概念に従って実装されています。 Genericsを使用しているため、この実装はHashTableクラスとは無関係ですが、Microsoftは内部的に同じコードを使用し、Object型のシンボルをTKeyとTValueに置き換えることができました。
.NET 1.0にはジェネリックは存在しませんでした。 HashTableとArrayListが最初に始まった場所です。
ハッシュ表:
キー/値はヒープに格納されている間、オブジェクト(ボクシング)型に変換されます。
キー/値は、ヒープから読み取る際に目的の型に変換する必要があります。
これらの操作は非常に費用がかかります。ボクシング/ボクシング解除をできるだけ避ける必要があります。
辞書: / HashTableの一般的な変種。
ボクシングはありません。変換は不要です。
Hashtableオブジェクトは、コレクションの要素を含むバケットから構成されています。バケットはHashtable内の要素の仮想サブグループ、 です。これにより、ほとんどのコレクション よりも検索と検索が容易かつ迅速になります。
DictionaryクラスはHashtableクラスと同じ機能を持ちます。 Hashtableの要素はObject型であるため、値を格納または取得する場合は通常ボクシングおよびアンボックス化が行われるため、特定の型のディクショナリ(Object以外) はHashtable よりも値型に対してパフォーマンスが高くなりますタイプ。
さらに読むために: ハッシュテーブルと辞書のコレクション型
私が理解できるもう一つの違いは:
WebサービスではDictionary <KT、VT>(総称)を使用することはできません。その理由は、Webサービス標準が総称標準をサポートしていないためです。
Dictionary<>
はジェネリック型なので、型安全です。
HashTableには任意の値型を挿入できます。これにより、例外が発生することがあります。しかしDictionary<int>
は整数値のみを受け付け、同様にDictionary<string>
は文字列のみを受け付けます。
そのため、HashTable
ではなくDictionary<>
を使用することをお勧めします。
もう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は挿入順を保持しませんが。
ほとんどのプログラミング言語では、辞書はハッシュテーブルよりも好まれています。
私はこれが必ずしも正しいとは思わない、彼らが好む 用語に依存して、ほとんどの言語はどちらか一方を持っている 。
しかし、C#では、(私にとって)明らかな理由は、C#HashTablesとSystem.Collections名前空間の他のメンバーがほとんど使われていないことです。それらはc#V1.1にありました。それらはC#2.0からSystem.Collections.Generic名前空間のGenericクラスに置き換えられました。