Dictionaries & HashSets in C# – Dictionary, HashSet

Dictionaries & HashSets in C# – Dictionary<TKey, TValue>, HashSet<T>

Dictionaries & HashSets in C# – Dictionary<TKey, TValue>, HashSet<T>

Introduction

In C#, when working with collections of data where uniqueness or fast lookup is important, Dictionary<TKey, TValue> and HashSet<T> are two of the most powerful and efficient data structures available. Both are implemented using hashing algorithms and provide fast access times, but they serve different purposes.

Dictionary<TKey, TValue> is a key-value pair collection that allows you to store and retrieve values based on a unique key, while HashSet<T> is a collection designed to store unique elements only—no duplicates allowed.

This guide explores both in depth, compares their syntax and performance, and explains when to use each effectively.

What is Dictionary<TKey, TValue>?

Dictionary<TKey, TValue> is a generic collection in the System.Collections.Generic namespace that stores data in a key-value format. It allows quick lookups, additions, and deletions using a unique key.

  • Fast Lookup: Retrieves values in constant time on average.
  • Unique Keys: Each key must be unique within the dictionary.
  • Type Safety: Strongly typed to prevent key/value mismatches.
Dictionary<int, string> users = new Dictionary<int, string>();
users.Add(1, "Alice");
users.Add(2, "Bob");

Console.WriteLine(users[1]); // Output: Alice

What is HashSet<T>?

HashSet<T> is a collection that stores only unique elements. It is part of the System.Collections.Generic namespace and provides high-performance set operations such as union, intersection, and difference.

  • No Duplicates: Automatically ignores repeated elements.
  • Optimized Lookup: Offers quick add, remove, and search operations.
  • Mathematical Sets: Useful for operations like union and intersection.
HashSet<string> tags = new HashSet<string>();
tags.Add("csharp");
tags.Add("dotnet");
tags.Add("csharp"); // Duplicate, will not be added

Console.WriteLine(tags.Count); // Output: 2

Dictionary vs HashSet: Core Differences

Though both Dictionary and HashSet are based on hash tables and provide fast access to data, their usage and data models differ significantly. Here's a side-by-side comparison:

Feature Dictionary<TKey, TValue> HashSet<T>
Data Structure Key-Value Pairs Single Values (Set)
Uniqueness Keys must be unique All elements must be unique
Access Method Via key (e.g., users[1]) Via methods (e.g., Contains)
Primary Use Lookup and mapping relationships Presence-checking, sets
Duplicates Values can repeat, keys cannot No duplicates allowed

Performance Comparison

Both Dictionary and HashSet offer constant-time operations on average—thanks to their use of hashing. However, the actual speed can depend on factors like hash collisions, load factor, and type complexity.

  • Add, Remove, Lookup: O(1) on average for both.
  • Memory Usage: Dictionary may consume more due to storing key-value pairs.
  • Iteration: Dictionary iterates over key-value pairs; HashSet over single elements.

Here's a sample to show how both perform basic tasks:

// Dictionary
var students = new Dictionary<int, string>();
students[101] = "Ava";
Console.WriteLine(students.ContainsKey(101)); // True

// HashSet
var studentIDs = new HashSet<int>();
studentIDs.Add(101);
Console.WriteLine(studentIDs.Contains(101)); // True

Use Cases for Dictionary<TKey, TValue>

Dictionaries are the best choice when you need to associate keys with values or perform fast key-based lookups. Typical scenarios include:

  • Mapping user IDs to usernames
  • Caching data by unique keys
  • Storing settings or configuration values
  • Counting frequency of items

Example: Count Word Frequency

string[] words = { "apple", "banana", "apple", "orange" };
Dictionary<string, int> wordCount = new Dictionary<string, int>();

foreach (var word in words)
{
    if (wordCount.ContainsKey(word))
        wordCount[word]++;
    else
        wordCount[word] = 1;
}

Use Cases for HashSet<T>

HashSet<T> excels when you need fast membership testing and set operations. It's ideal for:

  • Checking if an item already exists
  • Removing duplicates from a list
  • Performing unions and intersections
  • Tracking visited states or items

Example: Remove Duplicates

string[] names = { "Alice", "Bob", "Alice", "Charlie" };
HashSet<string> uniqueNames = new HashSet<string>(names);

foreach (var name in uniqueNames)
{
    Console.WriteLine(name);
}

Advanced Set Operations with HashSet<T>

HashSet<T> offers built-in methods to handle set-based logic efficiently—just like in mathematical set theory. These operations are highly optimized for performance.

  • UnionWith() – Combines two sets, removing duplicates
  • IntersectWith() – Keeps only elements found in both sets
  • ExceptWith() – Removes all elements that exist in another set

Example: Using IntersectWith

HashSet<int> set1 = new HashSet<int> { 1, 2, 3, 4 };
HashSet<int> set2 = new HashSet<int> { 3, 4, 5, 6 };

set1.IntersectWith(set2); // set1 now contains { 3, 4 }

Best Practices

  • Always check for key existence using ContainsKey() before accessing Dictionary values.
  • Use HashSet when uniqueness is key, and you don’t care about order or indexing.
  • Use Dictionary when mapping is necessary, not just presence checking.
  • Leverage LINQ with HashSet and Dictionary for more expressive code.

Conclusion

Dictionary<TKey, TValue> and HashSet<T> are foundational to efficient C# programming. Each has a purpose—Dictionaries are perfect for mapping and fast retrieval by key, while HashSets are unbeatable for ensuring uniqueness and quick membership tests.

In short:

  • Use Dictionary when you need key-value storage.
  • Use HashSet when you need unique elements with quick access.

Mastering these structures will help you write cleaner, faster, and more maintainable code.

FAQs

1. Can I use a custom class as a key in a Dictionary?

Yes, but you must override Equals() and GetHashCode() methods to ensure correct behavior.

2. Does HashSet preserve order?

No. If you need order and uniqueness, consider using SortedSet<T> or List<T> with manual filtering.

3. Can I store duplicate values in a Dictionary?

Yes, but only the keys must be unique. You can have duplicate values mapped to different keys.

4. Which one is thread-safe?

Neither is thread-safe by default. Use ConcurrentDictionary or locks for multi-threaded scenarios.

5. Can I convert a List to a HashSet?

Yes, simply pass the list into the HashSet constructor: new HashSet<T>(myList);

Post a Comment

Post a Comment (0)

Previous Post Next Post

ads

ads

Update cookies preferences