Languages like Java and C# expose a HashSet type for unique elements and fast membership tests. JavaScript does not spell HashSet in the standard library, but hashset javascript searches almost always want the same behavior: unique values, has in average sublinear time (implementations may use hash tables internally—see MDN Set), and predictable iteration. The built-in answer is Set. For javascript hash set style key → value storage with unique keys, use Map instead.
This guide shows Set construction, add deduplication, iteration, delete / has, object identity, array dedupe, and a tiny Map contrast.
Tested on: Node.js v20.18.2. A short note after each snippet describes what you should see in the console.
Quick reference
Use this table when you are translating Java HashSet / C# HashSet mental models into JavaScript: Set for unique values, Map for unique keys with payloads, [...new Set(arr)] to dedupe arrays.
| Goal | Type |
|---|---|
Unique values, membership has |
Set |
| Unique keys with associated values | Map |
| Dedupe array | [...new Set(arr)] |
1. Create a Set (hashset in javascript)
Constructing from an iterable seeds the set in one step; size reflects unique membership.
const theSet = new Set([1, 2, 3, 4, 5]);
console.log(theSet);You should see one line like: Set(5) { 1, 2, 3, 4, 5 }.
2. add ignores duplicates (js hashset behavior)
Repeated add with the same value is a no-op; only the first successful insertion affects order and size.
const mySet = new Set();
mySet.add("one");
mySet.add("one");
mySet.add("two");
mySet.add("three");
mySet.add("four");
mySet.add("five");
console.log(mySet);You should see one line like: Set(5) { 'one', 'two', 'three', 'four', 'five' }.
3. Iterate in insertion order with forEach
forEach visits each member once; callback order matches insertion order, not sort order.
const mySet = new Set(["one", "two", "three", "four", "five"]);
mySet.forEach(function (value) {
console.log(value);
});You should see 5 lines of output, starting with one and ending with five.
4. delete and has
delete removes by value; has answers membership without mutating the set. For boolean return values, clear(), and object-reference pitfalls, see JavaScript Set remove element.
const theSet = new Set(["one", "two", "three", "four", "five"]);
console.log(theSet);
theSet.delete("five");
console.log(theSet);
console.log(theSet.has("four"));You should see 3 lines: Set(5) { 'one', 'two', 'three', 'four', 'five' }, then Set(4) { 'one', 'two', 'three', 'four' }, then true.
5. Objects are compared by reference (hashset in js gotcha)
Primitives dedupe by value; objects dedupe only when the same reference is added twice.
Two different object literals are not equal under ===, so Set keeps both unless you delete the same reference you added.
const theSet = new Set();
theSet
.add({ user: "jack", has: false })
.add({ user: "Ox", has: true })
.add({ user: "femi", has: false });
theSet.forEach((data) => {
if (data.has === true) theSet.delete(data);
});
console.log(theSet);You should see one line like: Set(2) { { user: 'jack', has: false }, { user: 'femi', has: false } }.
For “unique by id” or “unique by serialized shape,” use a Map keyed by id/string, or normalize before add.
6. Dedupe an array; NaN counts once
Spreading a Set built from an array is the idiomatic one-liner dedupe; NaN follows SameValueZero rules.
console.log([...new Set([1, 2, 2, 3])]);
console.log(new Set([NaN, NaN]).size);You should see 2 lines: [ 1, 2, 3 ], then 1.
7. When people mean hash set javascript but need Map
Set is “bag of unique values.” When each record has a key and a payload, Map matches the mental model better.
const m = new Map([
["a", 1],
["b", 2],
]);
m.set("a", 3);
console.log(m.size);
console.log([...m.keys()]);You should see 2 lines: 2, then [ 'a', 'b' ].
Summary
The main takeaway: Set for unique values and fast has, Map for unique keys with values, [...new Set(arr)] for array dedupe—mind object identity and NaN.
Setstores each value at most once; iteration follows insertion order.add/has/delete/sizecover the usual hash-set operations; objects use reference identity.- Spread
new Set(arr)dedupes primitives;NaNis handled once under SameValueZero. - Use
Mapwhen each entry is a key paired with a value.
References
MDN and a Stack Overflow reference for HashSet-style collections in JavaScript.
Frequently Asked Questions
What is the JavaScript equivalent of a Java or C# HashSet?
Use the built-in Set object. It stores each value at most once and provides add, has, delete, and size for membership and mutation.
Is a JavaScript Set ordered or unordered?
Iteration follows insertion order—the order in which add succeeded. That differs from some textbook hash set descriptions that say unordered, so rely on insertion order for determinism, not on sorted order.
Why do two identical-looking objects both stay in a Set?
Set uses SameValueZero like === for non-NaN primitives, but for objects it uses reference identity. Two literal objects are two different references unless you add the same variable twice.
When should I use Map instead of Set for a hash set in javascript style workflow?
If each entry is a key paired with a value and keys must be unique, use Map. Set is for a bag of unique values without separate keys.
Does Set treat NaN as unique twice?
No. Because of SameValueZero, NaN is considered equal to itself inside a Set, so multiple add(NaN) calls still yield size 1.
How do I dedupe an array with a hashset in javascript?
Spread a Set built from the array: [...new Set(array)].
