webentwicklung-frage-antwort-db.com.de

Warum wird Wörterbuch in C # gegenüber Hashtable bevorzugt?

In den meisten Programmiersprachen werden Wörterbücher gegenüber Hashtabellen bevorzugt. Was sind die Gründe dafür?

1321
Nakul Chaudhary

Ein Dictionary ist (konzeptionell) eine Hash-Tabelle.

Wenn Sie meinten "Warum verwenden wir die Klasse Dictionary<TKey, TValue> anstelle der Klasse Hashtable?", Dann ist dies eine einfache Antwort: Dictionary<TKey, TValue> ist ein generischer Typ, Hashtable nicht . Das bedeutet, dass Sie mit Dictionary<TKey, TValue> Typensicherheit erhalten, da Sie kein zufälliges Objekt darin einfügen können und die Werte, die Sie herausnehmen, nicht umgewandelt werden müssen.

Interessanterweise basiert die Implementierung von Dictionary<TKey, TValue> in .NET Framework auf Hashtable, wie Sie aus diesem Kommentar im Quellcode ersehen können:

Das generische Wörterbuch wurde aus der Quelle von Hashtable kopiert

Quelle

1512
Michael Madsen

Dictionary <<< >>> Hashtable Unterschiede:

  • Generisch <<< >>> Nicht generisch
  • Benötigt eigene Thread-Synchronisation <<< >>> Bietet thread-sichere Version durch Synchronized() Methode
  • Aufzählung: KeyValuePair <<< >>> Aufzählung: DictionaryEntry
  • Neuere (> . NET 2.0 ) <<< >>> Ältere (seit . NET 1.0 )
  • ist in System.Collections.Generic <<< >>> ist in System.Collections
  • Anfrage an nicht existierenden Schlüssel löst Ausnahme aus <<< >>> Anfrage an nicht existierenden Schlüssel gibt null zurück
  • potenziell ein bisschen schneller für Werttypen <<< >>> Bit langsamer (benötigt Boxing/Unboxing) für Werttypen

Dictionary/Hashtable Ähnlichkeiten:

  • Beides sind interne Hashtabellen == schneller Zugriff auf viele Artikeldaten laut Schlüssel
  • Beide benötigen unveränderliche und eindeutige Schlüssel
  • Beide Schlüssel benötigen eine eigene GetHashCode() Methode

Ähnliche .NET-Sammlungen (Kandidaten, die anstelle von Dictionary und Hashtable verwendet werden sollen):

  • ConcurrentDictionary - thread safe (kann sicher von mehreren Threads gleichzeitig zugegriffen werden)
  • HybridDictionary - optimierte Leistung (für wenige Artikel und auch für viele Artikel)
  • OrderedDictionary - Auf Werte kann über int index zugegriffen werden (in der Reihenfolge, in der die Elemente hinzugefügt wurden)
  • SortedDictionary - Artikel automatisch sortiert
  • StringDictionary - stark typisiert und optimiert für Strings
603
Thetam

Da Dictionary eine generische Klasse ist (Dictionary<TKey, TValue>), ist der Zugriff auf deren Inhalt typsicher (dh Sie müssen nicht wie bei einer Object von Hashtable aus konvertieren) ] _).

Vergleichen Sie

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

zu

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

Dictionary wird jedoch intern als Hash-Tabelle implementiert, so dass es technisch genauso funktioniert.

175
gius

Hinweis: In .NET ist Hashtable thread-sicher für die Verwendung durch mehrere Reader-Threads und einen einzelnen Schreib-Thread, während in Dictionary öffentliche statische Member thread-sicher sind, aber es wird nicht garantiert, dass Instanzen-Member Thread sind sicher.

Aus diesem Grund mussten wir alle unsere Wörterbücher auf Hashtable zurücksetzen.

84
user38902

In .NET besteht der Unterschied zwischen Dictionary<,> und HashTable hauptsächlich darin, dass ersterer ein generischer Typ ist, sodass Sie alle Vorteile von Generika in Bezug auf die statische Typprüfung (und reduziertes Boxen) nutzen können 't so groß wie die Leute neigen dazu, in Bezug auf die Leistung zu denken - es gibt jedoch eine bestimmte Speicherkosten zum Boxen).

67
Marc Gravell

Die Leute sagen, dass ein Dictionary dasselbe ist wie eine Hash-Tabelle.

Dies ist nicht unbedingt wahr. Eine Hash-Tabelle ist eine Möglichkeit, ein Wörterbuch zu implementieren . Dabei handelt es sich um einen typischen Wert, der möglicherweise der Standardwert in .NET in der Klasse Dictionary ist, aber per Definition nicht der einzige.

Sie könnten ein Wörterbuch genauso gut mithilfe einer verknüpften Liste oder eines Suchbaums implementieren, es wäre einfach nicht so effizient (für einige Metriken von Effizienz).

33
rix0rrr

Collections & Generics sind nützlich für die Behandlung von Objektgruppen. In .NET befinden sich alle Objektgruppen unter der Schnittstelle IEnumerable, die wiederum ArrayList(Index-Value)) & HashTable(Key-Value) enthält. Nach .NET Framework 2.0 wurden ArrayList & HashTable durch List & Dictionary ersetzt. Jetzt werden die Arraylist & HashTable in heutigen Projekten nicht mehr verwendet.

Kommen wir zum Unterschied zwischen HashTable & Dictionary, Dictionary ist generisch, wobei Hastable nicht generisch ist. Wir können HashTable jeden Objekttyp hinzufügen, müssen ihn aber beim Abrufen in den erforderlichen Typ umwandeln. Es ist also nicht typsicher. Aber für dictionary können wir, während wir uns selbst deklarieren, den Typ des Schlüssels und den Wert angeben, sodass beim Abrufen keine Umwandlung erforderlich ist.

Schauen wir uns ein Beispiel an:

HashTable

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);
        }

    }
}

Wörterbuch,

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);
        }
    }
}
21
Sujit

Siehe Wörterbuch:

  • Es gibt/löst eine Ausnahme aus, wenn wir versuchen, einen Schlüssel zu finden, der nicht existiert.

  • Es ist schneller als ein Hashtable, da es kein Ein- und Auspacken gibt.

  • Nur öffentliche statische Mitglieder sind threadsicher.

  • Das Wörterbuch ist ein generischer Typ, das heißt, wir können ihn mit jedem Datentyp verwenden (beim Erstellen müssen die Datentypen sowohl für Schlüssel als auch für Werte angegeben werden).

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

  • Dictionay ist eine typsichere Implementierung von Hashtable. Keys und Values sind stark typisiert.

Hashtable:

  • Es gibt null zurück, wenn wir versuchen, einen Schlüssel zu finden, der nicht existiert.

  • Es ist langsamer als das Wörterbuch, da es das Ein- und Auspacken erfordert.

  • Alle Mitglieder in einer Hashtable sind threadsicher,

  • Hashtable ist kein generischer Typ.

  • Hashtable ist eine lose typisierte Datenstruktur. Wir können Schlüssel und Werte von jedem Typ hinzufügen.

16
Altaf Patel

Der Artikel mfassende Untersuchung von Datenstrukturen mit C # über MSDN besagt, dass es auch einen Unterschied in der Strategie zur Kollisionsauflösung gibt :

Die Hashtable-Klasse verwendet eine Technik, die als Wiederaufbereiten bezeichnet wird.

Das Aufwärmen funktioniert wie folgt: Es gibt eine Reihe von Hash-Funktionen, H1 ... Hnund beim Einfügen oder Abrufen eines Elements aus der Hash-Tabelle zunächst das H1 Hash-Funktion wird verwendet. Wenn dies zu einer Kollision führt, wird H2 wird stattdessen versucht und weiter bis zu Hn wenn benötigt.

Das Wörterbuch verwendet eine Technik, die als Verketten bezeichnet wird.

Beim erneuten Aufwärmen wird im Falle einer Kollision der Hash neu berechnet und der neue Schlitz, der einem Hash entspricht, wird ausprobiert. Bei der Verkettung wird jedoch eine sekundäre Datenstruktur verwendet, um etwaige Kollisionen zu speichern . Insbesondere verfügt jeder Slot im Dictionary über ein Array von Elementen, die diesem Bucket zugeordnet sind. Im Falle einer Kollision wird das kollidierende Element der Liste des Buckets vorangestellt.

15
alexandrekow

Seit .NET Framework 3.5 gibt es auch ein HashSet<T> , das alle Vorteile des Dictionary<TKey, TValue> bietet, wenn Sie nur die Schlüssel und keine Werte benötigen.

Wenn Sie also einen _Dictionary<MyType, object>_ verwenden und den Wert immer auf null setzen, um die typsichere Hash-Tabelle zu simulieren, sollten Sie möglicherweise in Betracht ziehen, auf HashSet<T> zu wechseln.

14
Oliver

Die Hashtable ist eine lose typisierte Datenstruktur, sodass Sie der Hashtable Schlüssel und Werte eines beliebigen Typs hinzufügen können. Die Dictionary -Klasse ist eine typsichere Hashtable -Implementierung, und die Schlüssel und Werte sind stark typisiert. Beim Erstellen einer Dictionary -Instanz müssen Sie die Datentypen sowohl für den Schlüssel als auch für den Wert angeben.

13
flesh

Beachten Sie, dass MSDN sagt: "Dictionary <(Of <(TKey, TValue>)>) Klasse wird als implementiert hash-tabelle", nicht" Dictionary <(Of <(TKey, TValue>)>) -Klasse ist als implementiert Hash-tabelle"

Das Wörterbuch wird NICHT als HashTable implementiert, sondern nach dem Konzept einer Hash-Tabelle. Die Implementierung hat aufgrund der Verwendung von Generics keine Beziehung zur HashTable-Klasse, obwohl Microsoft intern denselben Code hätte verwenden und die Symbole des Typs Object durch TKey und TValue ersetzen können.

In .NET 1.0 gab es keine Generika. Hier begannen ursprünglich HashTable und ArrayList.

11
Brant

HashTable:

Schlüssel/Wert werden beim Speichern im Heap in einen Objekttyp (Boxing-Typ) umgewandelt.

Schlüssel/Wert muss beim Lesen vom Heap in den gewünschten Typ konvertiert werden.

Diese Operationen sind sehr kostspielig. Wir müssen Boxen/Unboxen so weit wie möglich vermeiden.

Dictionary: Generische Variante von HashTable.

Kein Boxen/Unboxing. Keine Konvertierungen erforderlich.

Ein Hashtable-Objekt besteht aus Buckets, die die Elemente der Auflistung enthalten. Ein Bucket ist eine virtuelle Untergruppe von Elementen in der Hashtable , die das Suchen und Abrufen einfacher und schneller macht als in den meisten Sammlungen .

Die Dictionary-Klasse hat dieselbe Funktionalität wie die Hashtable-Klasse. Ein Dictionary eines bestimmten Typs (außer Object) hat eine bessere Leistung als eine Hashtable für Werttypen, da die Elemente von Hashtable vom Typ Object sind und daher , Boxing und Unboxing treten normalerweise auf, wenn ein Werttyp gespeichert oder abgerufen wird.

Weitere Informationen: Hashtable- und Dictionary-Sammlungstypen

8
mparkuk

Ein weiterer wichtiger Unterschied ist, dass Hashtable threadsicher ist. Hashtable verfügt über eine integrierte Thread-Sicherheit für mehrere Reader/Single Writer (MR/SW). Dies bedeutet, dass Hashtable EINEN Writer zusammen mit mehreren Readern ohne Sperren zulässt.

Im Fall von Dictionary gibt es keine Thread-Sicherheit. Wenn Sie Thread-Sicherheit benötigen, müssen Sie Ihre eigene Synchronisierung implementieren.

Um weiter auszuarbeiten:

Hashtable bietet eine gewisse Thread-Sicherheit durch die Synchronized -Eigenschaft, die einen thread-sicheren Wrapper um die Auflistung zurückgibt. Der Wrapper sperrt bei jedem Hinzufügen oder Entfernen die gesamte Sammlung. Daher muss jeder Thread, der versucht, auf die Auflistung zuzugreifen, warten, bis er an der Reihe ist, um die eine Sperre zu übernehmen. Dies ist nicht skalierbar und kann bei großen Sammlungen zu erheblichen Leistungseinbußen führen. Auch das Design ist nicht vollständig vor Rennbedingungen geschützt.

Die .NET Framework 2.0-Auflistungsklassen wie List<T>, Dictionary<TKey, TValue> usw. bieten keine Thread-Synchronisierung. Der Benutzercode muss die gesamte Synchronisierung bereitstellen, wenn Elemente in mehreren Threads gleichzeitig hinzugefügt oder entfernt werden

Wenn Sie sowohl Typensicherheit als auch Threadsicherheit benötigen, verwenden Sie gleichzeitige Auflistungsklassen in .NET Framework. Weitere Lektüre hier .

Ein weiterer Unterschied besteht darin, dass beim Hinzufügen der mehreren Einträge im Wörterbuch die Reihenfolge beibehalten wird, in der die Einträge hinzugefügt werden. Wenn wir die Elemente aus Dictionary abrufen, erhalten wir die Datensätze in der Reihenfolge, in der wir sie eingefügt haben. Während Hashtable die Einfügereihenfolge nicht beibehält.

6
NullReference

Ein weiterer Unterschied, den ich herausfinden kann, ist:

Wir können Dictionary <KT, VT> (Generics) nicht mit Webservices verwenden. Der Grund ist, dass kein Webservice-Standard den Generics-Standard unterstützt.

5
prashant

Dictionary<> ist ein generischer Typ und daher typsicher.

Sie können einen beliebigen Werttyp in HashTable einfügen, was manchmal zu einer Ausnahme führen kann. Aber Dictionary<int> akzeptiert nur ganzzahlige Werte und auf ähnliche Weise akzeptiert Dictionary<string> nur Zeichenfolgen.

Daher ist es besser, Dictionary<> anstelle von HashTable zu verwenden.

5
Kishore Kumar

In den meisten Programmiersprachen werden Wörterbücher gegenüber Hashtabellen bevorzugt

Ich denke nicht, dass dies unbedingt der Fall sein muss, die meisten Sprachen haben je nach Terminologie, die sie bevorzugen das eine oder andere.

In C # ist der eindeutige Grund (für mich), dass C # -HashTables und andere Mitglieder des System.Collections-Namespace weitgehend veraltet sind. Sie waren in c # V1.1 vorhanden. Sie wurden von C # 2.0 durch die Generic-Klassen im System.Collections.Generic-Namespace ersetzt.

0
kristianp