Ce face HashSet<T>
Clasa System.Collections.Generic.HashSet<T> reprezintă o mulțime matematică de elemente unice bazată pe o tabelă de dispersie. Este alegerea ideală ori de câte ori vrei să elimini automat duplicatele dintr-o colecție sau să verifici foarte frecvent dacă un element a fost deja procesat (set.Contains(x) rulează în timp constant O(1), în timp ce lista.Contains(x) pe o List<T> scanează liniar element cu element în O(n)).
Metoda set.Add(element) returnează o valoare booleană extrem de utilă: true dacă elementul nu exista și a fost adăugat cu succes, respectiv false dacă elementul era deja prezent în mulțime (fără a arunca vreo excepție). În plus, HashSet<T> oferă operații rapide pe mulțimi precum reuniunea (UnionWith), intersecția (IntersectWith) și diferența (ExceptWith).
Parametri, metode și opțiuni
| Parametru / Metodă | Descriere |
|---|---|
set.Add(T item) |
Încearcă să adauge elementul în mulțime; returnează true dacă elementul este nou sau false dacă exista deja. |
set.Contains(T item) |
Verifică în timp constant O(1) dacă elementul se află în mulțime. |
set.UnionWith(IEnumerable<T> other) |
Adaugă în mulțimea curentă toate elementele din other (reuniunea mulțimilor). |
set.IntersectWith(IEnumerable<T> other) |
Păstrează în mulțimea curentă doar elementele care apar și în other (intersecția mulțimilor). |
set.ExceptWith(IEnumerable<T> other) |
Elimină din mulțimea curentă toate elementele care se regăsesc în other (diferența mulțimilor). |
set.SetEquals(IEnumerable<T> other) |
Verifică dacă mulțimea conține exact aceleași elemente unice ca secvența other, indiferent de ordine. |
Exemple
Exemplul 1: Deduplicarea rapidă și detectarea elementelor deja văzute cu Add()
Folosim valoarea booleană returnată de Add() pentru a filtra într-o singură trecere ID-urile duplicate dintr-un lot de tranzacții.
int[] idTranzactii = [501, 502, 503, 501, 504, 502];
var procesate = new HashSet<int>();
foreach (int id in idTranzactii)
{
if (procesate.Add(id))
{
Console.WriteLine($"Tranzacția #{id} a fost procesată.");
}
else
{
Console.WriteLine($"[IGNORAT] Tranzacție duplicată #{id}!");
}
}
Ieșire în consolă
Tranzacția #501 a fost procesată.
Tranzacția #502 a fost procesată.
Tranzacția #503 a fost procesată.
[IGNORAT] Tranzacție duplicată #501!
Tranzacția #504 a fost procesată.
[IGNORAT] Tranzacție duplicată #502!
Exemplul 2: Operații pe mulțimi: IntersectWith și ExceptWith
Determinăm permisiunile comune și pe cele lipsă dintre două roluri de utilizator.
var permisiuniEditor = new HashSet<string> { "read", "write", "upload" };
var permisiuniAdmin = new HashSet<string> { "read", "write", "delete", "manage_users" };
var doarLaAdmin = new HashSet<string>(permisiuniAdmin);
doarLaAdmin.ExceptWith(permisiuniEditor);
var comune = new HashSet<string>(permisiuniEditor);
comune.IntersectWith(permisiuniAdmin);
Console.WriteLine("Comune: " + string.Join(", ", comune));
Console.WriteLine("Doar la Admin: " + string.Join(", ", doarLaAdmin));
Ieșire în consolă
Comune: read, write
Doar la Admin: delete, manage_users
Greșeli frecvente
- Folosirea unei
List<T>în locul unuiHashSet<T>atunci când apelezi.Contains(...)în interiorul unei bucle — înlocuirea listei cuHashSet<T>reduce complexitatea totală de laO(n²)laO(n). - Presupunerea că
HashSet<T>garantează păstrarea ordinii de inserare sau sortarea elementelor (după ștergeri și reinserări, ordinea internă se poate schimba); dacă ai nevoie de o mulțime ordonată, foloseșteSortedSet<T>.
Funcții și concepte înrudite
Dictionary<TKey, TValue>: Stochează perechi cheie-valoare într-o tabelă de dispersie (hash table) cu căutare, inserare și ștergere în timp constant O(1).List<T>: Stochează o listă generică redimensionabilă dinamic, cu acces rapid după index și metode de adăugare, ștergere și căutare.Enumerable.Where: Filtrează declarativ o secvență de elemente pe baza unui predicat lambda, cu execuție amânată (deferred execution).