web-dev-qa-db-fra.com

Pourquoi dictionnaire est-il préférable à Hashtable en C #?

Dans la plupart des langages de programmation, les dictionnaires sont préférés aux hashtables. Quelles sont les raisons derrière cela?

1321
Nakul Chaudhary

Pour ce que ça vaut, un dictionnaire est (conceptuellement) une table de hachage.

Si vous vouliez dire "pourquoi utilisons-nous la classe Dictionary<TKey, TValue> au lieu de la classe Hashtable?", La réponse est simple: Dictionary<TKey, TValue> est un type générique, Hashtable n'est pas . Cela signifie que vous obtenez la sécurité de type avec Dictionary<TKey, TValue>, car vous ne pouvez y insérer aucun objet aléatoire et vous n'avez pas à convertir les valeurs que vous extrayez.

Fait intéressant, l'implémentation Dictionary<TKey, TValue> dans le .NET Framework est basée sur la Hashtable, comme vous pouvez le constater à partir de ce commentaire dans son code source:

Le dictionnaire générique a été copié à partir de la source de Hashtable

Source

1512
Michael Madsen

Dictionary <<< >>> Hashtable différences:

  • Générique <<< >>> Non générique
  • Nécessite sa propre synchronisation de fil <<< >>> Offre la version thread-safe par la méthode Synchronized()
  • Item énuméré: KeyValuePair <<< >>> Item énuméré: DictionaryEntry
  • Plus récent (> . NET 2.0 ) <<< >>> Plus ancien (depuis . NET 1.0 )
  • est dans System.Collections.Generic <<< >>> est dans System.Collections
  • Une requête sur une clé non existante lève une exception <<< >>> Une requête sur une clé non existante renvoie la valeur null
  • potentiellement un bit plus rapide pour les types de valeur <<< >>> bit plus lent (nécessite boxing/unboxing) pour les types de valeur

Dictionary/Hashtable similitudes:

  • Les deux sont internes hashtables == accès rapide aux données de nombreux éléments en fonction de la clé
  • Les deux ont besoin de clés uniques et immuables
  • Les clés des deux doivent posséder la méthode GetHashCode()

Collections similaires .NET (candidats à utiliser à la place de Dictionary et Hashtable):

  • ConcurrentDictionary - thread safe (accessible en toute sécurité depuis plusieurs threads simultanément)
  • HybridDictionary - performances optimisées (pour quelques articles et également pour de nombreux articles)
  • OrderedDictionary - les valeurs peuvent être accessibles via int index (par ordre dans lequel les éléments ont été ajoutés)
  • SortedDictionary - éléments triés automatiquement
  • StringDictionary - fortement typé et optimisé pour les chaînes
603
Thetam

Parce que Dictionary est une classe générique (Dictionary<TKey, TValue>), l'accès à son contenu est donc sûr pour le type (c'est-à-dire que vous n'avez pas besoin de transtyper à partir de Object, comme avec un Hashtable).

Comparer

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

à

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

Cependant, Dictionary est implémenté en tant que table de hachage en interne, donc techniquement, il fonctionne de la même manière.

175
gius

FYI: Dans .NET, Hashtable est thread-safe pour une utilisation par plusieurs threads de lecture et un seul thread d'écriture, alors que dans Dictionary, les membres statiques publics sont thread-safe, mais aucun membre d'instance n'est nécessairement thread. sûr.

Pour cette raison, nous avons dû changer tous nos dictionnaires en Hashtable.

84
user38902

Dans .NET, la différence entre Dictionary<,> et HashTable est principalement que le premier est un type générique. Vous bénéficiez ainsi de tous les avantages des génériques en termes de vérification de type statique (et de pas aussi gros que ce que les gens ont tendance à penser en termes de performance - il y a cependant un coût mémoire indéniable pour la boxe).

67
Marc Gravell

Les gens disent qu'un dictionnaire est la même chose qu'une table de hachage.

Ce n'est pas forcément vrai. Une table de hachage est un moyen de implémenter un dictionnaire. Un exemple typique, qui peut être celui par défaut dans .NET dans la classe Dictionary, mais ce n'est pas par définition le seul.

Vous pourriez également bien mettre en place un dictionnaire en utilisant une liste chaînée ou un arbre de recherche, cela ne serait tout simplement pas aussi efficace (pour une métrique d’efficace).

33
rix0rrr

Collections & Generics sont utiles pour gérer des groupes d'objets. Dans .NET, tous les objets de collections entrent dans l'interface IEnumerable, qui a elle-même ArrayList(Index-Value)) & HashTable(Key-Value). Après .NET Framework 2.0, ArrayList & HashTable ont été remplacés par List & Dictionary. Maintenant, les Arraylist & HashTable ne sont plus utilisés dans les projets actuels.

En ce qui concerne la différence entre HashTable & Dictionary, Dictionary est générique, alors que Hastable n'est pas générique. Nous pouvons ajouter n'importe quel type d'objet à HashTable, mais lors de la récupération, nous devons le transtyper vers le type requis. Donc, ce n'est pas sûr. Mais pour dictionary, tout en se déclarant, nous pouvons spécifier le type de clé et la valeur, il n’est donc pas nécessaire de lancer la conversion lors de la récupération.

Regardons un exemple:

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

    }
}

Dictionnaire,

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

Dictionnaire:

  • Il retourne/jette Exception si nous essayons de trouver une clé qui n'existe pas.

  • C'est plus rapide qu'une table de hachage car il n'y a pas de boxe ni de déballage.

  • Seuls les membres statiques publics sont thread-safe.

  • Le dictionnaire est un type générique, ce qui signifie que nous pouvons l’utiliser avec n’importe quel type de données (lors de la création, vous devez spécifier les types de données pour les clés et les valeurs).

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

  • Dictionay est une implémentation de Hashtable adaptée aux types, Keys et Values sont fortement typés.

Hashtable:

  • Il retourne null si nous essayons de trouver une clé qui n'existe pas.

  • Il est plus lent que dictionnaire car il nécessite la boxe et le déballage.

  • Tous les membres d'une table de hachage sont thread-safe,

  • Hashtable n'est pas un type générique,

  • Hashtable est une structure de données faiblement typée, nous pouvons ajouter des clés et des valeurs de tout type.

16
Altaf Patel

L'article Examen approfondi des structures de données en utilisant C # sur MSDN indique qu'il existe également une différence dans la stratégie de résolution de collision :

La classe Hashtable utilise une technique appelée rehashing .

Le rehachage fonctionne comme suit: il existe un ensemble de fonctions de hachage différentes, H1 ... Hnet lors de l'insertion ou de l'extraction d'un élément de la table de hachage, le H1 La fonction de hachage est utilisée. Si cela entraîne une collision, H2 est essayé à la place, et jusqu'à Hn si besoin.

Le dictionnaire utilise une technique appelée chaînage .

En cas de collision, le hachage est recalculé et le nouvel emplacement correspondant à un hachage est essayé. Avec le chaînage, cependant, , une structure de données secondaire est utilisée pour contenir toutes les collisions . Plus précisément, chaque emplacement du dictionnaire contient un tableau d’éléments mappés sur ce compartiment. En cas de collision, l'élément en collision est ajouté à la liste du compartiment.

15
alexandrekow

Depuis .NET Framework 3.5, il existe également un HashSet<T> qui fournit tous les avantages du Dictionary<TKey, TValue> si vous n'avez besoin que des clés et pas de valeurs.

Ainsi, si vous utilisez un _Dictionary<MyType, object>_ et que vous définissez toujours la valeur null pour simuler la table de hachage de type sécuritaire, vous devriez peut-être envisager de basculer vers le HashSet<T> .

14
Oliver

La variable Hashtable est une structure de données faiblement typée. Vous pouvez donc ajouter des clés et des valeurs de tout type à la variable Hashtable. La classe Dictionary est une implémentation Hashtable de type sûr; les clés et les valeurs sont fortement typées. Lors de la création d'une instance Dictionary, vous devez spécifier les types de données pour la clé et la valeur.

13
flesh

Notez que MSDN indique: "La classe Dictionary <(Of <(TKey, TValue>)>) est implémentée en tant que table de hachageLa classe "Dictionary <(Of <(TKey, TValue>)>>") est implémentée en tant que HashTable"

Le dictionnaire n'est PAS implémenté en tant que HashTable, mais il est implémenté selon le concept de table de hachage. L'implémentation n'est pas liée à la classe HashTable à cause de l'utilisation de Generics, bien que Microsoft puisse en interne utiliser le même code et remplacer les symboles de type Object par TKey et TValue.

Dans .NET 1.0, les génériques n’existaient pas; C'est ici que HashTable et ArrayList ont commencé.

11
Brant

HashTable:

La clé/valeur sera convertie en un type d'objet (boxing) lors de son stockage dans le tas.

La clé/valeur doit être convertie dans le type souhaité lors de la lecture du tas.

Ces opérations sont très coûteuses. Nous devons éviter de boxer/déballer autant que possible.

Dictionary: Variante générique de HashTable.

Pas de boxe/unboxing. Aucune conversion requise.

8

Un objet Hashtable est constitué de compartiments contenant les éléments de la collection. Un compartiment est un sous-groupe virtuel d'éléments de la table de hachage , qui facilite et accélère la recherche et la récupération par rapport à la plupart des collections .

La classe Dictionary a les mêmes fonctionnalités que la classe Hashtable. Un dictionnaire d'un type spécifique (autre que Object) offre de meilleures performances qu'un Hashtable pour les types valeur, car les éléments de Hashtable sont de type Object et, par conséquent, , boxing et unboxing se produisent généralement lors du stockage ou de la récupération d'un type de valeur.

Pour en savoir plus: Types de collections Hashtable et Dictionary

8
mparkuk

Une autre différence importante est que Hashtable est thread-safe. Hashtable intègre une sécurité de thread de plusieurs lecteurs/graveurs uniques (MR/SW), ce qui signifie que Hashtable autorise ONE writer avec plusieurs lecteurs sans verrouillage.

Dans le cas de Dictionary, il n'y a pas de sécurité de thread; si vous avez besoin de la sécurité des threads, vous devez implémenter votre propre synchronisation.

Pour élaborer plus avant:

Hashtable fournit une sécurité de thread par le biais de la propriété Synchronized, qui renvoie un wrapper thread-safe autour de la collection. Le wrapper fonctionne en verrouillant toute la collection à chaque opération d'ajout ou de suppression. Par conséquent, chaque thread qui tente d'accéder à la collection doit attendre son tour pour prendre le même verrou. Ce n'est pas évolutif et peut entraîner une dégradation significative des performances pour les grandes collections. En outre, la conception n'est pas complètement protégée des conditions de concurrence.

Les classes de la collection .NET Framework 2.0 telles que List<T>, Dictionary<TKey, TValue>, etc. ne fournissent aucune synchronisation de thread; le code utilisateur doit fournir toute la synchronisation lorsque des éléments sont ajoutés ou supprimés simultanément sur plusieurs threads

Si vous avez besoin de la sécurité des types et des threads, utilisez des classes de collections simultanées dans le .NET Framework. Lectures supplémentaires ici .

Une différence supplémentaire est que, lorsque nous ajoutons les entrées multiples dans Dictionnaire, l'ordre dans lequel les entrées sont ajoutées est conservé. Lorsque nous récupérons les éléments de Dictionary, nous obtenons les enregistrements dans le même ordre que nous les avons insérées. Considérant que Hashtable ne conserve pas l'ordre d'insertion.

6
NullReference

Une autre différence que je peux comprendre est la suivante:

Nous ne pouvons pas utiliser Dictionary <KT, VT> (génériques) avec les services Web. La raison en est qu’aucune norme de service Web ne prend en charge la norme générique.

5
prashant

Dictionary<> est un type générique et est donc sûr.

Vous pouvez insérer n'importe quel type de valeur dans HashTable, ce qui peut parfois générer une exception. Mais Dictionary<int> n'acceptera que des valeurs entières. De même, Dictionary<string> n'acceptera que des chaînes.

Il est donc préférable d’utiliser Dictionary<> au lieu de HashTable.

5
Kishore Kumar

Dans la plupart des langages de programmation, les dictionnaires sont préférés aux hashtables

Je ne pense pas que cela soit nécessairement vrai, la plupart des langues ont l’une ou l’autre, selon le terminologie qu’elles préfèrent .

En C #, cependant, la raison (pour moi) est que les tables de hachage C # et les autres membres de l’espace de noms System.Collections sont en grande partie obsolètes. Ils étaient présents dans c # V1.1. Elles ont été remplacées à partir de C # 2.0 par les classes génériques de l'espace de noms System.Collections.Generic.

0
kristianp