HashSet<T>
HashSet<T> lagrar element utan dubletter och utan garanterad ordning. Contains, Add och Remove kostar O(1) — oberoende av hur stor samlingen är.
TL;DR
- Inga dubletter —
Addignorerar element som redan finns och returnerarfalse. - Ingen ordning — iterationsordning är odefinierad.
Containsär konstant tid, till skillnad frånList<T>som ärO(n).- Stöd för mängdoperationer: union, snitt, differens.
Grundläggande användning
var uniqueColours = new HashSet<string>();
bool added = uniqueColours.Add("Röd"); // truebool added = uniqueColours.Add("Blå"); // truebool added = uniqueColours.Add("Röd"); // false — finns redan
Console.WriteLine(uniqueColours.Count); // 2
// Skapa från array — dubletter faller bort automatisktstring[] arr = { "Röd", "Blå", "Grön", "Röd", "Blå", "Gul" };var unique = new HashSet<string>(arr);Console.WriteLine(unique.Count); // 4Vanliga metoder
var number = new HashSet<int> { 1, 2, 3, 4, 5 };
number.Add(6); // true — lades tillnumber.Add(3); // false — finns redannumber.Contains(3); // true — O(1)number.Remove(5); // true — borttagetnumber.Count; // antal element
// Jämförelsevar another = new HashSet<int> { 4, 3, 2, 1, 6 };number.SetEquals(another); // true — samma element, ordning spelar ingen roll
var subset = new HashSet<int> { 1, 2, 3 };subset.IsSubsetOf(number); // truenumber.IsSupersetOf(subset); // truenumber.Overlaps(new HashSet<int> { 3, 7, 8 }); // true — delar elementet 3Mängdoperationer
var a = new HashSet<string> { "Anna", "Pelle", "Kalle" };var b = new HashSet<string> { "Pelle", "Sara", "Johan" };
// Union — alla element från båda (inga dubletter)var union = new HashSet<string>(a);union.UnionWith(b); // { Anna, Pelle, Kalle, Sara, Johan }
// Snitt — bara vad som finns i bådavar average = new HashSet<string>(a);average.IntersectWith(b); // { Pelle }
// Differens — vad som finns i a men inte bvar difference = new HashSet<string>(a);difference.ExceptWith(b); // { Anna, Kalle }
// Symmetrisk differens — vad som finns i exakt ett av demvar symDiff = new HashSet<string>(a);symDiff.SymmetricExceptWith(b); // { Anna, Kalle, Sara, Johan }Metoderna modifierar originalet. Skapa alltid en kopia (new HashSet<T>(original)) om du vill behålla ursprungssamlingen.
Praktiska användningsfall
// Ta bort dubletter från en listaList<string> medDubletter = new List<string> { "Anna", "Pelle", "Anna", "Kalle", "Pelle" };List<string> unique = new HashSet<string>(medDubletter).ToList();
// Snabb behörighetskontrollvar allowedUser = new HashSet<string> { "admin", "moderator", "editor" };if (allowedUser.Contains(inloggadUser)) { /* ... */ }
// Spåra besökta noder i en graftraverseringvar visited = new HashSet<int>();void DFS(GraphNode nod){ if (!visited.Add(nod.Id)) return; // Add returnerar false om den redan finns foreach (var neighbour in nod.Neighbours) DFS(neighbour);}HashSet vs List — när vilket?
| Egenskap | HashSet<T> | List<T> |
|---|---|---|
| Dubletter | Tillåts inte | Tillåts |
| Ordning | Ingen | Bevaras |
| Indexering | Nej | Ja |
| Contains | O(1) | O(n) |
| Add | O(1) amorterat | O(1) amorterat |
| Mängdoperationer | Inbyggda | Saknas |
Välj HashSet<T> när du behöver unikhet eller snabb uppslagning. Välj List<T> när ordning eller indexering spelar roll.
Anpassad likhetslogik
Om du lagrar egna objekt måste du implementera Equals och GetHashCode, annars jämförs referenserna — inte innehållet.
public class Person{ public string Name { get; set; } public int Age { get; set; }
public override bool Equals(object? obj) => obj is Person p && Name == p.Name && Age == p.Age;
public override int GetHashCode() => HashCode.Combine(Name, Age);}
var people = new HashSet<Person>();people.Add(new Person { Name = "Pelle", Age = 25 });people.Add(new Person { Name = "Pelle", Age = 25 }); // ignoreras — likaCase-insensitiv jämförelse för strängar:
var emails = new HashSet<string>(StringComparer.OrdinalIgnoreCase);emails.Add("pelle@example.com");emails.Add("PELLE@EXAMPLE.COM"); // ignorerasÖvningar
- Ta bort dubletter från en lista med 10 namn och skriv ut hur många unika som finns kvar.
- Givet två listor med behörigheter, hitta vilka behörigheter som är gemensamma.
- Bygg en besöksräknare som skiljer på första besök och återkommande besök.