HashSet în C# (.NET)

Colecții generice .NET 3.5+

Menține o mulțime neordonată de elemente unice cu verificare de apartenență în timp O(1) și operații matematice pe mulțimi.

Sintaxă C#
var set = new HashSet<string>(); bool esteNou = set.Add("valoare");

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 unui HashSet<T> atunci când apelezi .Contains(...) în interiorul unei bucle — înlocuirea listei cu HashSet<T> reduce complexitatea totală de la O(n²) la O(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ște SortedSet<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).