Pouvez-vous expliquer quelle est la différence entre HashSet<T>
et List<T>
dans .NET?
Peut-être pouvez-vous expliquer par un exemple dans quels cas HashSet<T>
il faut préférer List<T>
?
Pouvez-vous expliquer quelle est la différence entre HashSet<T>
et List<T>
dans .NET?
Peut-être pouvez-vous expliquer par un exemple dans quels cas HashSet<T>
il faut préférer List<T>
?
Réponses:
Contrairement à une liste <> ...
Un HashSet est une liste sans membres en double.
Parce qu'un HashSet est contraint de ne contenir que des entrées uniques, la structure interne est optimisée pour la recherche (par rapport à une liste) - c'est considérablement plus rapide
L'ajout à un HashSet renvoie un booléen - false si l'ajout échoue en raison de l'existence déjà dans l'ensemble
Peut effectuer des opérations d'ensemble mathématiques sur un ensemble: Union / Intersection / IsSubsetOf etc.
HashSet n'implémente pas IList uniquement ICollection
Vous ne pouvez pas utiliser d'index avec un HashSet, uniquement des énumérateurs.
La principale raison d'utiliser un HashSet serait si vous souhaitez effectuer des opérations Set.
Étant donné 2 ensembles: hashSet1 et hashSet2
//returns a list of distinct items in both sets
HashSet set3 = set1.Union( set2 );
vole en comparaison avec une opération équivalente utilisant LINQ. C'est aussi plus soigné à écrire!
Union
méthode. J'avais utilisé à la UnionWith
place.
Pour être plus précis, démontrons avec des exemples,
Vous ne pouvez pas utiliser HashSet comme dans l'exemple suivant.
HashSet<string> hashSet1 = new HashSet<string>(){"1","2","3"};
for (int i = 0; i < hashSet1.Count; i++)
Console.WriteLine(hashSet1[i]);
hashSet1[i]
produirait une erreur:
Impossible d'appliquer l'indexation avec [] à une expression de type "System.Collections.Generic.HashSet"
Vous pouvez utiliser l'instruction foreach:
foreach (var item in hashSet1)
Console.WriteLine(item);
Vous ne pouvez pas ajouter d'éléments dupliqués à HashSet alors que List vous permet de le faire et pendant que vous ajoutez un élément à HashSet, vous pouvez vérifier s'il contient l'élément ou non.
HashSet<string> hashSet1 = new HashSet<string>(){"1","2","3"};
if (hashSet1.Add("1"))
Console.WriteLine("'1' is successfully added to hashSet1!");
else
Console.WriteLine("'1' could not be added to hashSet1, because it contains '1'");
HashSet a quelques fonctions utiles comme IntersectWith
, UnionWith
, IsProperSubsetOf
, ExceptWith
, SymmetricExceptWith
etc.
IsProperSubsetOf
:
HashSet<string> hashSet1 = new HashSet<string>() { "1", "2", "3", "4" };
HashSet<string> hashSet2 = new HashSet<string>() { "2", "4", "6", "8" };
HashSet<string> hashSet3 = new HashSet<string>() { "1", "2", "3", "4", "5" };
if (hashSet1.IsProperSubsetOf(hashSet3))
Console.WriteLine("hashSet3 contains all elements of hashSet1.");
if (!hashSet1.IsProperSubsetOf(hashSet2))
Console.WriteLine("hashSet2 does not contains all elements of hashSet1.");
UnionWith
:
HashSet<string> hashSet1 = new HashSet<string>() { "3", "4" };
HashSet<string> hashSet2 = new HashSet<string>() { "2", "4", "6", "8" };
hashSet1.UnionWith(hashSet2); //hashSet1 -> 3, 2, 4, 6, 8
IntersectWith
:
HashSet<string> hashSet1 = new HashSet<string>() { "3", "4", "8" };
HashSet<string> hashSet2 = new HashSet<string>() { "2", "4", "6", "8" }
hashSet1.IntersectWith(hashSet2);//hashSet1 -> 4, 8
ExceptWith
:
HashSet<string> hashSet1 = new HashSet<string>() { "1", "2", "3", "5", "6" };
HashSet<string> hashSet2 = new HashSet<string>() { "1", "2", "3", "4" };
hashSet1.ExceptWith(hashSet2);//hashSet1 -> 5, 6
SymmetricExceptWith
:
HashSet<string> hashSet1 = new HashSet<string>() { "1", "2", "3", "5", "6" };
HashSet<string> hashSet2 = new HashSet<string>() { "1", "2", "3", "4" };
hashSet1.SymmetricExceptWith(hashSet2);//hashSet1 -> 4, 5, 6
À propos, l'ordre n'est pas conservé dans les HashSets. Dans l'exemple, nous avons ajouté l'élément "2" en dernier mais il est dans le second ordre:
HashSet<string> hashSet1 = new HashSet<string>() { "3", "4", "8" };
hashSet1.Add("1"); // 3, 4, 8, 1
hashSet1.Remove("4"); // 3, 8, 1
hashSet1.Add("2"); // 3, 2 ,8, 1
A HashSet<T>
est une classe conçue pour vous donner une O(1)
recherche de confinement (c'est-à-dire, cette collection contient-elle un objet particulier et dites-moi la réponse rapidement).
A List<T>
est une classe conçue pour vous donner une collection avec O(1)
un accès aléatoire qui peut croître dynamiquement (pensez tableau dynamique). Vous pouvez tester le confinement dans le O(n)
temps (à moins que la liste ne soit triée, vous pouvez alors effectuer une recherche binaire dans le O(log n)
temps).
Peut-être pouvez-vous expliquer avec un exemple dans quels cas
HashSet<T>
il faut préférerList<T>
Lorsque vous souhaitez tester le confinement dans O(1)
.
Utilisez un List<T>
lorsque vous souhaitez:
Si vous connaissez l'index de l'élément souhaité (plutôt que la valeur de l'élément lui-même), la récupération est O(1)
. Si vous ne connaissez pas l'index, la recherche de l'élément prend plus de temps, O(n)
pour une collection non triée.
Utilisez un Hashset<T>
lorsque vous souhaitez:
Si vous connaissez le nom de la chose que vous voulez trouver, Lookup est O(1)
(c'est la partie 'Hash'). Il ne maintient pas un ordre comme le List<T>
fait et vous ne pouvez pas stocker de doublons (l'ajout d'un doublon n'a aucun effet, c'est la partie 'Set').
Un exemple de quand utiliser un Hashset<T>
serait si vous voulez savoir si un mot joué dans une partie de Scrabble est un mot valide en anglais (ou dans une autre langue). Ce serait encore mieux si vous vouliez créer un service Web à utiliser par toutes les instances d'une version en ligne d'un tel jeu.
Un List<T>
serait une bonne structure de données pour créer le tableau de bord pour suivre les scores des joueurs.
La liste est une liste ordonnée. C'est
HashSet est un ensemble. Il:
La liste est plus appropriée lorsque vous souhaitez accéder à votre collection comme s'il s'agissait d'un tableau auquel vous pourriez ajouter, insérer et supprimer des éléments. HashSet est un meilleur choix si vous voulez traiter votre collection comme un "sac" d'articles dans lequel l'ordre n'est pas important ou lorsque vous voulez le comparer avec d'autres ensembles en utilisant les opérations telles que IntersectWith ou UnionWith.
La liste n'est pas nécessairement unique, tandis que hashset l'est, pour un.
Une liste est une collection ordonnée d'objets de type T qui, contrairement à un tableau, vous pouvez ajouter et supprimer des entrées.
Vous utiliseriez une liste dans laquelle vous souhaitez référencer les membres dans l'ordre dans lequel vous les avez stockés et vous y accédez par une position plutôt que par l'élément lui-même.
Un HashSet est comme un dictionnaire que l'élément lui-même est la clé ainsi que la valeur, le classement n'est pas garanti.
Vous utiliseriez un HashSet où vous voulez vérifier qu'un objet est dans la collection
List
maintient un ordre (c'est-à-dire quand les choses ont été ajoutées), mais ne trie pas automatiquement les éléments. Vous devrez appeler .Sort
ou utiliser un SortedList
.
Si vous décidez d'appliquer ces structures de données à l'utilisation réelle dans le développement piloté par les données, un HashSet est TRÈS utile pour tester la réplication par rapport aux sources d'adaptateur de données, pour le nettoyage et la migration des données.
De plus, si vous utilisez la classe DataAnnotations, vous pouvez implémenter la logique de clé sur les propriétés de classe et contrôler efficacement un index naturel (en cluster ou non) avec un HashSet, où cela serait très difficile dans une implémentation List.
Une option intéressante pour utiliser une liste consiste à implémenter des génériques pour plusieurs supports sur un modèle de vue, comme l'envoi d'une liste de classes à une vue MVC pour un assistant DropDownList, et également pour l'envoi en tant que construction JSON via WebApi. La liste permet une logique de collecte de classe typique, et conserve la flexibilité pour une approche plus «interface» pour calculer un modèle de vue unique sur différents supports.