Domanda

Puoi spiegare qual è la differenza tra HashSet<T> e List<T> in .NET?

Forse puoi spiegare con un esempio in quali casi HashSet<T> dovrebbe essere preferito rispetto a List<T>?

È stato utile?

Soluzione

A differenza di un elenco <> ...

  1. Un HashSet è un elenco senza membri duplicati.

  2. Poiché un HashSet è vincolato a contenere solo voci univoche, la struttura interna è ottimizzata per la ricerca (rispetto a un elenco): è notevolmente più veloce

  3. L'aggiunta a un HashSet restituisce un valore booleano - false se l'aggiunta non riesce perché già esistente in Set

  4. Può eseguire operazioni matematiche sugli insiemi su un insieme: Union / Intersection / IsSubsetOf ecc.

  5. HashSet non implementa IList solo ICollection

  6. Non è possibile utilizzare indici con un HashSet, solo enumeratori.

Il motivo principale per utilizzare un HashSet sarebbe se sei interessato a eseguire operazioni Set.

Dati 2 set: hashSet1 e hashSet2

 //returns a list of distinct items in both sets
 HashSet set3 = set1.Union( set2 );

vola rispetto a un'operazione equivalente che utilizza LINQ.È anche più carino scrivere!

Altri suggerimenti

Un HashSet<T> è una classe progettata per darti una ricerca O(1) per il contenimento (ad esempio, questa raccolta contiene un oggetto particolare e dimmi la risposta velocemente).

Un List<T> è una classe progettata per fornire una raccolta con accesso casuale O(1) che può crescere dinamicamente (si pensi all'array dinamico).Puoi testare il contenimento nel tempo O(n) (a meno che l'elenco non sia ordinato, puoi eseguire una ricerca binaria nel tempo O(log n)).

Forse puoi spiegare con un esempio in quali casi HashSet<T> dovrebbe essere preferito rispetto a List<T>

Quando si desidera testare il contenimento in O(1).

Per essere più precisi, dimostriamo con esempi,

Non è possibile utilizzare HashSet come nell'esempio seguente.

HashSet<string> hashSet1 = new HashSet<string>(){"1","2","3"};
for (int i = 0; i < hashSet1.Count; i++)
    Console.WriteLine(hashSet1[i]);

hashSet1[i] produrrebbe un errore:

Impossibile applicare l'indicizzazione con [] a un'espressione di tipo "System.Collections.Generic.HashSet"

Puoi utilizzare l'istruzione foreach:

foreach (var item in hashSet1)
    Console.WriteLine(item);

Non puoi aggiungere elementi duplicati a HashSet mentre List ti consente di farlo e mentre aggiungi un elemento a HashSet, puoi controllare se contiene l'elemento o meno.

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 ha alcune funzioni utili come IntersectWith, UnionWith, IsProperSubsetOf, ExceptWith, SymmetricExceptWith ecc.

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

A proposito, l'ordine non viene mantenuto in HashSets. Nell'esempio, abbiamo aggiunto l'elemento "2" per ultimo ma è nel secondo ordine:

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

Usa un List<T> quando vuoi:

  • Memorizza una raccolta di elementi in un determinato ordine.

Se conosci l'indice dell'elemento che desideri (piuttosto che il valore dell'elemento stesso), il recupero è O(1). Se non conosci l'indice, la ricerca dell'elemento richiede più tempo, genera un codice tag per una raccolta non ordinata.

Usa un O(n) quando vuoi:

  • Scopri rapidamente se un determinato oggetto è contenuto in una raccolta.

Se conosci il nome della cosa che vuoi trovare, Lookup è Hashset<T> (questa è la parte "Hash"). Non mantiene un ordine come fa il O(1) e non puoi memorizzare duplicati (l'aggiunta di un duplicato non ha effetto, questa è la parte "Imposta").

Un esempio di quando utilizzare un List<T> sarebbe se vuoi scoprire se una parola giocata in una partita a Scrabble è una parola valida in inglese (o in un'altra lingua). Ancora meglio sarebbe se volessi creare un servizio web che possa essere utilizzato da tutte le istanze di una versione online di un gioco del genere.

Un Hashset<T> sarebbe una buona struttura di dati per creare il tabellone segnapunti per tenere traccia dei punteggi dei giocatori.

L'elenco è un elenco ordinato.Lo è

  • accessibile da un indice intero
  • può contenere duplicati
  • ha un ordine prevedibile

HashSet è un set.It:

  • Può bloccare elementi duplicati (vedi Aggiungi (T) )
  • Non garantisce l'ordine degli articoli all'interno del set
  • Dispone di operazioni che ti aspetteresti su un set, ad esempio , IntersectWith, IsProperSubsetOf, UnionWith.

List è più appropriato quando vuoi accedere alla tua collezione come se fosse come un array a cui puoi aggiungere, inserire e rimuovere elementi.HashSet è una scelta migliore se vuoi trattare la tua collezione come una "borsa" di articoli in cui l'ordine non è importante o quando vuoi confrontarla con altri set utilizzando operazioni come IntersectWith o UnionWith.

List non è necessariamente univoco, mentre hashset lo è, per prima cosa.

Una lista è una raccolta ordinata di oggetti di tipo T che, a differenza di un array, puoi aggiungere e rimuovere voci.

Dovresti utilizzare un elenco in cui desideri fare riferimento ai membri nell'ordine in cui li hai memorizzati e stai accedendo a loro da una posizione piuttosto che dall'elemento stesso.

Un HashSet è come un dizionario in cui l'elemento stesso è la chiave oltre che il valore, l'ordine non è garantito.

Dovresti utilizzare un HashSet in cui desideri verificare che un oggetto sia nella raccolta

Se decidi di applicare queste strutture di dati all'utilizzo effettivo nello sviluppo basato sui dati, un HashSet è MOLTO utile per testare la replica rispetto alle origini dell'adattatore di dati, per la pulizia e la migrazione dei dati.

Inoltre, se si utilizza la classe DataAnnotations, è possibile implementare la logica Key sulle proprietà della classe e controllare efficacemente un indice naturale (cluster o meno) con un HashSet, dove ciò sarebbe molto difficile in un'implementazione di List.

Una valida opzione per l'utilizzo di un elenco consiste nell'implementare generici per più mezzi su un modello di visualizzazione, come l'invio di un elenco di classi a una vista MVC per un DropDownList Helper e anche per l'invio come costrutto JSON tramite WebApi.L'elenco consente una tipica logica di raccolta di classi e mantiene la flessibilità per un approccio più simile a "Interfaccia" per l'elaborazione di un modello di visualizzazione singola per mezzi diversi.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top