Mastering Usage of HashSet<T>
Introduction to HashSet<T>
In C#, HashSet<T>
is a high-performance collection class designed to store unique elements in an unordered manner. It belongs to the System.Collections.Generic
namespace and implements the ISet<T>
interface. Unlike List<T>
or arrays, HashSet<T>
automatically enforces uniqueness—attempting to add a duplicate element has no effect.
Why Use HashSet<T>?
Fast Lookups: Built on a hash table,
HashSet<T>
provides O(1) average time complexity for search, insertion, and deletion.Memory Efficiency: Optimized to handle large datasets efficiently.
Set Operations: Supports mathematical set operations like Union, Intersection, and Difference.
No Duplicates: Ensures all elements are unique without manual checks.
Key Features of HashSet<T>
Feature | Description |
---|---|
Uniqueness | Automatically rejects duplicate values. |
Unordered Storage | Elements are not stored in any particular order. |
Fast Operations | Add() , Remove() , and Contains() run in O(1) time on average. |
Set Operations | Supports UnionWith() , IntersectWith() , and ExceptWith() . |
Custom Equality | Allows defining custom equality logic via IEqualityComparer<T> . |
Basic Operations with HashSet<T>
1. Creating and Initializing a HashSet
2. Adding and Removing Elements
3. Checking for Existence
4. Counting Elements
5. Iterating Over Elements
Output:
Advanced HashSet<T> Operations
1. Set Operations (Union, Intersection, Difference)
Union (UnionWith
)
Combines two sets, keeping only unique elements.
Intersection (IntersectWith
)
Keeps only elements present in both sets.
Difference (ExceptWith
)
Removes elements that exist in another set.
2. Custom Equality Comparison
By default, HashSet<T>
uses Equals()
and GetHashCode()
. You can override these or use a custom IEqualityComparer<T>
.
Example: Case-Insensitive String HashSet
Example: Custom Object Comparison
Performance Considerations
Operation | Time Complexity | Notes |
---|---|---|
Add() | O(1) | Fast, but may degrade if many hash collisions occur. |
Remove() | O(1) | Efficient deletion. |
Contains() | O(1) | Best for frequent lookups. |
UnionWith() | O(N) | Depends on the size of the other set. |
When to Use HashSet<T>?
✔ Removing duplicates from a list.
✔ Checking membership (e.g., "Is this username taken?").
✔ Mathematical set operations (union, intersection).
When NOT to Use HashSet<T>?
❌ Order matters (use List<T>
or SortedSet<T>
instead).
❌ Frequent indexed access (no HashSet[index]
).
Practical Example: Removing Duplicates from a List
Output: [1, 2, 3, 4, 5]
Thread Safety & Alternatives
HashSet<T>
is not thread-safe. For concurrent scenarios:
Use
ConcurrentDictionary<TKey, TValue>
(if key-value pairs are needed).Use
lock
for manual synchronization.
Conclusion
HashSet<T>
is a powerful collection for storing unique elements with fast lookups and set operations. It excels in:
✅ Ensuring uniqueness without manual checks.
✅ Optimizing search operations (O(1) time).
✅ Performing set-based logic (union, intersection).
By mastering HashSet<T>
, you can write more efficient and cleaner C# code when dealing with unique data.