Definire: che cos'è un HashSet?


420

HashSet La struttura di dati HashSet C # è stata introdotta in .NET Framework 3.5. Un elenco completo dei membri implementati è disponibile nella pagina MSDN di HashSet .

  1. Dove è usato?
  2. Perché dovresti usarlo?



Usa una hashtable internamente. se hai una buona implementazione hashtable (ad esempio Dizionario <T>) puoi implementare HashSet facilmente.
Raz Megrelidze,

Risposte:


614
    1. A HashSetcontiene un set di oggetti, ma consente di determinare facilmente e rapidamente se un oggetto è già nel set o meno. Lo fa gestendo internamente un array e memorizzando l'oggetto usando un indice che viene calcolato dall'hashcode dell'oggetto. Dai un'occhiata qui

    2. HashSetè una raccolta non ordinata contenente elementi unici. Ha le operazioni di raccolta standard Aggiungi, Rimuovi, Contiene, ma poiché utilizza un'implementazione basata su hash, queste operazioni sono O (1). (A differenza di List, ad esempio, che è O (n) per Contiene e Rimuovi.) HashSetFornisce anche operazioni di serie standard come unione , intersezione e differenza simmetrica . Dai un'occhiata qui

  1. Esistono diverse implementazioni di set. Alcuni rendono le operazioni di inserimento e ricerca super veloci grazie agli elementi di hashing. Tuttavia, ciò significa che si perde l'ordine in cui sono stati aggiunti gli elementi. Altre implementazioni preservano l'ordine aggiunto a costo di tempi di esecuzione più lenti.

La HashSetclasse in C # va per il primo approccio, quindi non preservando l'ordine degli elementi. È molto più veloce di un normale List. Alcuni benchmark di base hanno mostrato che HashSet è decisamente più veloce quando si tratta di tipi primari (int, double, bool, ecc.). È molto più veloce quando si lavora con oggetti di classe. Quindi quel punto è che HashSet è veloce.

L'unica cattura di HashSetè che non vi è accesso da parte degli indici. Per accedere agli elementi è possibile utilizzare un enumeratore o utilizzare la funzione incorporata per convertire HashSetin a Liste scorrere attraverso quello. Dai un'occhiata qui


13
Due cose, hashset e simili sono .NET, non C #. Anche HashSet non conserva l'ordine. Prova ad aggiungere e rimuovere elementi da un set di hash, saprai se
ripeterai

13

A HashSetha una struttura interna (hash), in cui gli oggetti possono essere cercati e identificati rapidamente. Il rovescio della medaglia è che iterare attraverso un HashSet(o ottenere un oggetto per indice) è piuttosto lento.

Quindi perché qualcuno dovrebbe voler sapere se esiste già una voce in un set?

Una situazione in cui a HashSetè utile è ottenere valori distinti da un elenco in cui possono esistere duplicati. Una volta aggiunto un articolo HashSet, è rapido determinare se esiste ( Containsoperatore).

Altri vantaggi del HashSetsono le operazioni Set: IntersectWith, IsSubsetOf, IsSupersetOf, Overlaps, SymmetricExceptWith, UnionWith.

Se hai familiarità con il linguaggio del vincolo oggetto , identificherai queste operazioni impostate. Vedrai anche che è un passo avanti verso l'implementazione di UML eseguibile.


20
Ri: aspetto negativo. No, iterare attraverso un HashSet è perfettamente veloce. In secondo luogo, non è possibile ottenere un articolo per indice. In effetti, gli elementi sono memorizzati non ordinati.
Nigel Touch,

@Nigel Touch. L'iterazione è veloce se non ti interessa l'indice (ordine in cui sono stati aggiunti). Tuttavia, se sei preoccupato per l'indice, allora l'indice deve essere memorizzato con ogni chiave hash e quindi può essere piuttosto lento perché l'elenco deve essere cercato in modo esaustivo per recuperare l'elemento corretto. Questo comportamento è molto diverso da un elenco in cui gli elementi sono indicizzati dall'ordine in cui vengono aggiunti.
k Rey,

Ha senso perché sarebbe veloce, perché non esistono due hash uguali. Consentire alla query di trarre vantaggio da un approccio di "cortocircuito", escludendo rapidamente determinati criteri.
Chef_Code

8

Detto semplicemente e senza rivelare i segreti della cucina: un set in generale, è una collezione che non contiene elementi duplicati e i cui elementi non sono in un ordine particolare. Quindi, A HashSet<T>è simile a un generico List<T>, ma è ottimizzato per ricerche veloci (tramite hashtable, come suggerisce il nome) a costo di perdere l'ordine.


1
Ma un HashSet <T> può archiviare due oggetti con gli stessi dati, come due classi di prodotti che hanno ciascuna le stesse proprietà con lo stesso contenuto?
Johan Herstad,

Immagino che non lo sapremo mai
Denny il

@JohanHerstad Supponendo che EqualityComparer per la tua classe si preoccupi di quelle proprietà o costruisci l'HashSet con un IEqualityComparer che si prende cura di quelle proprietà, non vedo perché non dovrebbe. La documentazione per HashSet chiarisce che si basa sull'uno o sull'altro per determinare l'unicità.
Bacon Bits

2

Dal punto di vista dell'applicazione, se uno deve solo evitare i duplicati, allora HashSetè quello che stai cercando poiché è la complessità di ricerca, inserimento e rimozione sono O (1) . Ciò significa che non importa quanti elementi HashSetha lo stesso tempo ci vorrà per controllare se c'è un tale elemento o meno, inoltre poiché stai inserendo elementi anche su O (1) lo rende perfetto per questo genere di cose.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.