What Is a HashSet?
A HashSet is a hash-based data structure designed to store a collection of unique elements. Unlike a HashMap, which stores data as key-value pairs, a HashSet stores values where each value can appear only once.
HashSet is useful when the main requirement is to quickly determine whether an element exists and to prevent duplicate values.
const languages = new Set();
languages.add("JavaScript");
languages.add("Python");
languages.add("JavaScript");
console.log(languages);
// Set(2) { "JavaScript", "Python" }
The second "JavaScript" value is ignored because a Set does not store
duplicate values.
HashSet vs HashMap
HashSet and HashMap both use hashing concepts, but they solve different problems.
| Feature | HashSet | HashMap |
|---|---|---|
| Stores | Values | Key-value pairs |
| Duplicates | Not allowed | Keys are unique |
| Main purpose | Unique values and membership | Key-based lookup |
| Typical lookup | Is this value present? | What value belongs to this key? |
How a HashSet Works
A HashSet typically uses a hash function to transform each value into a hash value. The hash is then used to determine where the value should be stored.
Value → Hash Function → Hash Value → Bucket → Stored Value
When a value is added, the implementation calculates its hash and checks the corresponding location. If an equivalent value is already present, another copy is not inserted.
The exact implementation differs between programming languages, but the underlying idea is to use hashing for efficient membership operations.
Creating a HashSet in JavaScript
JavaScript provides the built-in Set object for HashSet-style behavior.
A Set stores unique values and provides operations for insertion, membership checking,
deletion, and iteration.
const users = new Set();
users.add("John");
users.add("Maya");
users.add("Alex");
console.log(users);
You can also create a Set from an existing iterable such as an array.
const numbers = new Set([10, 20, 30, 20, 10]);
console.log(numbers);
// Set(3) { 10, 20, 30 }
Adding Elements to a HashSet
Use add() to insert an element. Adding a value that already exists does
not create a duplicate.
const skills = new Set();
skills.add("HTML");
skills.add("CSS");
skills.add("JavaScript");
skills.add("JavaScript");
console.log(skills);
// Set(3) { "HTML", "CSS", "JavaScript" }
The JavaScript add() method returns the Set itself, which also allows
chained calls.
const skills = new Set();
skills
.add("HTML")
.add("CSS")
.add("JavaScript");
Checking Whether an Element Exists
The has() operation checks whether a value is present in the HashSet.
const roles = new Set([
"Developer",
"Designer",
"Tester"
]);
console.log(roles.has("Developer"));
// true
console.log(roles.has("Manager"));
// false
Membership checking is one of the main reasons to use a HashSet instead of repeatedly scanning an array.
Removing Elements
Use delete() to remove a value. The method returns true when
an element was removed and false when the value was not present.
const languages = new Set([
"JavaScript",
"Python",
"Java"
]);
console.log(languages.delete("Python"));
// true
console.log(languages.delete("C#"));
// false
console.log(languages);
Getting the Size of a HashSet
The size property tells you how many unique elements are currently stored.
const numbers = new Set([10, 20, 20, 30]);
console.log(numbers.size);
// 3
Iterating Through a HashSet
A HashSet can be traversed when you need to process each unique value.
const technologies = new Set([
"HTML",
"CSS",
"JavaScript"
]);
for (const technology of technologies) {
console.log(technology);
}
JavaScript Sets also provide values() and keys(). For a Set,
both represent the stored values.
for (const value of technologies.values()) {
console.log(value);
}
Removing All Elements
Use clear() when the entire HashSet should be emptied.
const users = new Set([
"John",
"Maya",
"Alex"
]);
users.clear();
console.log(users.size);
// 0
Using HashSet to Remove Duplicates
A common HashSet use case is removing duplicate values from a collection. In JavaScript, an array can be converted to a Set and then converted back into an array.
const numbers = [10, 20, 10, 30, 20, 40];
const uniqueNumbers = [...new Set(numbers)];
console.log(uniqueNumbers);
// [10, 20, 30, 40]
This is particularly useful when an application receives repeated IDs, tags, categories, or other values that should be unique.
HashSet and Set Operations
A mathematical set can be combined with another set using operations such as union, intersection, and difference. JavaScript's Set object does not require these operations to be performed using a special HashSet class; they can be implemented with iteration and membership checks.
Union
The union contains values that appear in either set.
const frontend = new Set(["HTML", "CSS", "JavaScript"]);
const backend = new Set(["C#", "JavaScript", "SQL"]);
const union = new Set([...frontend, ...backend]);
console.log(union);
// HTML, CSS, JavaScript, C#, SQL
Intersection
The intersection contains values that exist in both sets.
const frontend = new Set(["HTML", "CSS", "JavaScript"]);
const backend = new Set(["C#", "JavaScript", "SQL"]);
const common = new Set(
[...frontend].filter(skill => backend.has(skill))
);
console.log(common);
// JavaScript
Difference
The difference contains values that exist in the first set but not in the second.
const frontend = new Set(["HTML", "CSS", "JavaScript"]);
const backend = new Set(["C#", "JavaScript", "SQL"]);
const onlyFrontend = new Set(
[...frontend].filter(skill => !backend.has(skill))
);
console.log(onlyFrontend);
// HTML, CSS
HashSet and Object Values
A HashSet can also contain objects. However, object uniqueness is based on object identity rather than automatically comparing whether two objects contain the same data.
const users = new Set();
const user1 = { id: 1, name: "John" };
const user2 = { id: 1, name: "John" };
users.add(user1);
users.add(user2);
console.log(users.size);
// 2
Although both objects contain the same properties and values, they are separate object references. If uniqueness should be based on an ID, store the IDs in a Set instead.
const userIds = new Set();
userIds.add(1);
userIds.add(1);
console.log(userIds.size);
// 1
HashSet Time Complexity
HashSet implementations are generally designed to provide constant-time average performance for basic membership and modification operations.
| Operation | Average | Worst Case |
|---|---|---|
| Add | O(1) | O(n) |
| Search / Contains | O(1) | O(n) |
| Delete | O(1) | O(n) |
Actual performance depends on factors such as the quality of hashing, collision handling, load factor, resizing, and the specific implementation.
HashSet Space Complexity
A HashSet requires storage for the elements and its internal hash-table structures.
If n unique elements are stored, the typical space complexity is
O(n).
HashSet vs Array
Both arrays and HashSets can store collections of values, but their strengths are different.
| Feature | Array | HashSet |
|---|---|---|
| Duplicates | Allowed | Not stored |
| Membership search | O(n) with includes() | O(1) average |
| Index access | Supported | Not index-based |
| Primary purpose | Ordered collection | Unique values and membership |
HashSet vs HashMap
Choose a HashSet when you only need to know whether values exist. Choose a HashMap when each key needs to be associated with additional information.
// HashSet
const visited = new Set();
visited.add("page-home");
visited.add("page-profile");
// HashMap
const userRoles = new Map();
userRoles.set("u101", "Developer");
userRoles.set("u102", "Designer");
HashSet in Duplicate Detection
A Set can detect duplicate values while processing an array. Keep track of values that have already appeared and check membership before adding the next value.
function hasDuplicate(numbers) {
const seen = new Set();
for (const number of numbers) {
if (seen.has(number)) {
return true;
}
seen.add(number);
}
return false;
}
console.log(hasDuplicate([10, 20, 30, 20]));
// true
console.log(hasDuplicate([10, 20, 30, 40]));
// false
The algorithm avoids comparing every pair of elements. With average O(1) Set membership checks, the overall approach takes O(n) average time and O(n) additional space.
HashSet in Graph Algorithms
HashSets are frequently used with graph traversal algorithms such as BFS and DFS to track vertices that have already been visited.
const graph = {
A: ["B", "C"],
B: ["A", "D"],
C: ["A"],
D: ["B"]
};
const visited = new Set();
function dfs(node) {
if (visited.has(node)) {
return;
}
visited.add(node);
for (const neighbor of graph[node] ?? []) {
dfs(neighbor);
}
}
dfs("A");
console.log(visited);
// Set { "A", "B", "D", "C" }
Without a visited Set, a graph containing cycles could cause the traversal to repeatedly process the same vertices.
When Should You Use a HashSet?
A HashSet is a natural choice when uniqueness or fast membership checking is more important than positional access.
- Removing duplicate values.
- Checking whether an item has already been processed.
- Tracking visited graph nodes.
- Maintaining a collection of unique IDs.
- Detecting duplicate records.
- Checking membership efficiently.
- Maintaining unique tags or categories.
- Comparing collections using set operations.
Common HashSet Mistakes
Expecting Index-Based Access
A HashSet is not an array. It does not provide direct access using positions such as
set[0]. If your application needs frequent index-based access, an array
may be a better fit.
Assuming Duplicate Objects Are Automatically Removed
Objects can be considered different when they are different references. If uniqueness is based on an ID or another property, explicitly store that identifying value or implement the appropriate equality strategy in the language being used.
Assuming HashSet Operations Are Always O(1)
Hash-based structures generally provide O(1) average performance, not an unconditional O(1) guarantee for every implementation and workload. Poor hashing and collisions can affect performance.
Using a HashSet When Values Need to Be Sorted
A basic HashSet is focused on uniqueness and membership. If maintaining sorted order is a core requirement, a tree-based set or sorting step may be more appropriate.
HashSet in Coding Interviews
HashSet is a common interview tool because many problems can be simplified by tracking which values have already appeared.
- Find duplicate elements.
- Find the first repeated value.
- Find the first unique value with additional counting logic.
- Track visited nodes in graphs.
- Detect cycles or repeated states in certain algorithms.
- Determine whether two collections share common values.
- Remove duplicates from input data.
Practical Example: Unique Developer Skills
Imagine an application collecting skills from multiple projects. The same skill may appear repeatedly, but the final profile should contain each skill only once.
const projectSkills = [
"JavaScript",
"TypeScript",
"Angular",
"JavaScript",
"C#",
"Angular",
"SQL"
];
const uniqueSkills = new Set(projectSkills);
console.log([...uniqueSkills]);
// [
// "JavaScript",
// "TypeScript",
// "Angular",
// "C#",
// "SQL"
// ]
console.log(uniqueSkills.has("Angular"));
// true
The Set provides both uniqueness and efficient membership checking without requiring separate duplicate-removal logic.
HashSet: Key Characteristics
| Characteristic | Description |
|---|---|
| Storage | Unique values |
| Lookup | Hash-based membership checking |
| Duplicates | Not stored |
| Average add | O(1) |
| Average search | O(1) |
| Average delete | O(1) |
| Typical space | O(n) |
Key Takeaways
- A HashSet stores unique values rather than key-value pairs.
- Hashing enables efficient average-case membership operations.
- Adding an existing value does not create a duplicate.
- JavaScript's
Setprovides HashSet-style functionality. - HashSets are useful for duplicate detection and removal.
- They are commonly used to track visited elements in graph algorithms.
- Average insertion, search, and deletion are typically O(1).
- A HashSet is not designed for index-based access.
- If sorted order or positional access is required, another data structure may be more suitable.