Ok, I have tested adding, iterating and removing elements from both an array and a set. I ran a "small" test, using 10 000 elements and a "big" test, using 100 000 elements. Here are the results.

Adding elements to a collection

It would seem that the .push array method is about 4 times faster than the .add set method, no matter the number of elements being added.

Iterating over and modifying elements in a collection

For this part of the test I used a for loop to iterate over the array and a for of loop to iterate over the set. Again, iterating over the array was faster. This time it would seem that it is exponentially so as it took twice as long during the "small" tests and almost four times longer during the "big" tests.

Removing elements from a collection

Now this is where it gets interesting. I used a combination of a for loop and .splice to remove some elements from the array and I used for of and .delete to remove some elements from the set. For the "small" tests, it was about three times faster to remove items from the set (2.6 ms vs 7.1 ms) but things changed drastically for the "big" test where it took 1955.1 ms to remove items from the array while it only took 83.6 ms to remove them from the set, 23 times faster.

Conclusions

At 10k elements, both tests ran comparable times (array: 16.6 ms, set: 20.7 ms) but when dealing with 100k elements, the set was the clear winner (array: 1974.8 ms, set: 83.6 ms) but only because of the removing operation. Otherwise the array was faster. I couldn't say exactly why that is.

I played around with some hybrid scenarios where an array was created and populated and then converted into a set where some elements would be removed, the set would then be reconverted into an array. Although doing this will give much better performance than removing elements in the array, the additional processing time needed to transfer to and from a set outweighs the gains of populating an array instead of a set. In the end, it is faster to only deal with a set. Still, it is an interesting idea, that if one chooses to use an array as a data collection for some big data that doesn't have duplicates, it could be advantageous performance wise, if there is ever a need to remove many elements in one operation, to convert the array to a set, perform the removal operation, and convert the set back to an array.

Array code:

var timer = function(name) {
  var start = new Date();
  return {
    stop: function() {
      var end = new Date();
      var time = end.getTime() - start.getTime();
      console.log('Timer:', name, 'finished in', time, 'ms');
    }
  }
};

var getRandom = function(min, max) {
  return Math.random() * (max - min) + min;
};

var lastNames = ['SMITH', 'JOHNSON', 'WILLIAMS', 'JONES', 'BROWN', 'DAVIS', 'MILLER', 'WILSON', 'MOORE', 'TAYLOR', 'ANDERSON', 'THOMAS'];

var genLastName = function() {
  var index = Math.round(getRandom(0, lastNames.length - 1));
  return lastNames[index];
};

var sex = ["Male", "Female"];

var genSex = function() {
  var index = Math.round(getRandom(0, sex.length - 1));
  return sex[index];
};

var Person = function() {
  this.name = genLastName();
  this.age = Math.round(getRandom(0, 100))
  this.sex = "Male"
};

var genPersons = function() {
  for (var i = 0; i < 100000; i++)
    personArray.push(new Person());
};

var changeSex = function() {
  for (var i = 0; i < personArray.length; i++) {
    personArray[i].sex = genSex();
  }
};

var deleteMale = function() {
  for (var i = 0; i < personArray.length; i++) {
    if (personArray[i].sex === "Male") {
      personArray.splice(i, 1)
      i--
    }
  }
};

var t = timer("Array");

var personArray = [];

genPersons();

changeSex();

deleteMale();

t.stop();

console.log("Done! There are " + personArray.length + " persons.")

Set code:

var timer = function(name) {
    var start = new Date();
    return {
        stop: function() {
            var end  = new Date();
            var time = end.getTime() - start.getTime();
            console.log('Timer:', name, 'finished in', time, 'ms');
        }
    }
};

var getRandom = function (min, max) {
  return Math.random() * (max - min) + min;
};

var lastNames = ['SMITH','JOHNSON','WILLIAMS','JONES','BROWN','DAVIS','MILLER','WILSON','MOORE','TAYLOR','ANDERSON','THOMAS'];

var genLastName = function() {
    var index = Math.round(getRandom(0, lastNames.length - 1));
    return lastNames[index];
};

var sex = ["Male", "Female"];

var genSex = function() {
    var index = Math.round(getRandom(0, sex.length - 1));
    return sex[index];
};

var Person = function() {
	this.name = genLastName();
	this.age = Math.round(getRandom(0,100))
	this.sex = "Male"
};

var genPersons = function() {
for (var i = 0; i < 100000; i++)
	personSet.add(new Person());
};

var changeSex = function() {
	for (var key of personSet) {
		key.sex = genSex();
	}
};

var deleteMale = function() {
	for (var key of personSet) {
		if (key.sex === "Male") {
			personSet.delete(key)
		}
	}
};

var t = timer("Set");

var personSet = new Set();

genPersons();

changeSex();

deleteMale();

t.stop();

console.log("Done! There are " + personSet.size + " persons.")

Answer from snowfrogdev on Stack Overflow
🌐
DEV Community
dev.to › arnaud › using-array-prototype-includes-vs-set-prototype-has-to-filter-arrays-41fg
Using Array.prototype.includes() vs Set.prototype.has() to filter arrays - DEV Community
July 2, 2020 - Length of values to keep: 1 Length of values to test: 10 includes: 0.207ms has: 0.190ms Length of values to keep: 10 Length of values to test: 100 includes: 0.020ms has: 0.017ms Length of values to keep: 100 Length of values to test: 1000 includes: 0.204ms has: 0.071ms Length of values to keep: 1000 Length of values to test: 10000 includes: 9.942ms has: 1.307ms Length of values to keep: 10000 Length of values to test: 100000 includes: 131.686ms has: 8.016ms Length of values to keep: 100000 Length of values to test: 1000000 includes: 1324.318ms has: 71.495ms · So yes, I am right that with a small quantity of data, Array.includes and Set.has perform roughly the same, but we can see how quickly performance degrades, and the change is so small that it's hard to justify not making it, even for small data samples.
Discussions

JavaScript Set vs. Array performance - Stack Overflow
For Safari Set is significantly faster than key in Object and Object.hasOwnProperty is barely in the same realm of speed. All array variants (for loops/includes) are as expected dramatically slower than set/object look ups. More on stackoverflow.com
🌐 stackoverflow.com
I discovered Set exists for the first time today... Is it really faster?
I use sets, maps, and spread syntax all the time. I’ve never “done the math” to see the specs of the speed for sets. Maps have methods that are way faster when trying to search and filter things in big data sets. More on reddit.com
🌐 r/learnjavascript
26
11
July 24, 2024
Time complexity of array.prototype.includes vs. set.prototype.has
I've been reading conflicting answers about modern javascript engines' time complexity when it comes to sets vs arrays in javascript. I completed the demo task of codility, which is a simple assign... More on stackoverflow.com
🌐 stackoverflow.com
Am I wrong to think that the “has” method for Sets is better for time complexity vs “includes” for Arrays?
Looking at your example, you're already iterating on the array, so why not use !!array[i] instead? More on reddit.com
🌐 r/learnjavascript
15
1
October 13, 2020
🌐
Brian Douglass
bhdouglass.com › home › blog › node.js performance: array.includes vs set.has
Node.js Performance: Array.includes vs Set.has | Brian Douglass
December 14, 2024 - However, if you have an array and want to convert it to a set to use Set.has() you probably shouldn’t.
Top answer
1 of 7
182

Ok, I have tested adding, iterating and removing elements from both an array and a set. I ran a "small" test, using 10 000 elements and a "big" test, using 100 000 elements. Here are the results.

Adding elements to a collection

It would seem that the .push array method is about 4 times faster than the .add set method, no matter the number of elements being added.

Iterating over and modifying elements in a collection

For this part of the test I used a for loop to iterate over the array and a for of loop to iterate over the set. Again, iterating over the array was faster. This time it would seem that it is exponentially so as it took twice as long during the "small" tests and almost four times longer during the "big" tests.

Removing elements from a collection

Now this is where it gets interesting. I used a combination of a for loop and .splice to remove some elements from the array and I used for of and .delete to remove some elements from the set. For the "small" tests, it was about three times faster to remove items from the set (2.6 ms vs 7.1 ms) but things changed drastically for the "big" test where it took 1955.1 ms to remove items from the array while it only took 83.6 ms to remove them from the set, 23 times faster.

Conclusions

At 10k elements, both tests ran comparable times (array: 16.6 ms, set: 20.7 ms) but when dealing with 100k elements, the set was the clear winner (array: 1974.8 ms, set: 83.6 ms) but only because of the removing operation. Otherwise the array was faster. I couldn't say exactly why that is.

I played around with some hybrid scenarios where an array was created and populated and then converted into a set where some elements would be removed, the set would then be reconverted into an array. Although doing this will give much better performance than removing elements in the array, the additional processing time needed to transfer to and from a set outweighs the gains of populating an array instead of a set. In the end, it is faster to only deal with a set. Still, it is an interesting idea, that if one chooses to use an array as a data collection for some big data that doesn't have duplicates, it could be advantageous performance wise, if there is ever a need to remove many elements in one operation, to convert the array to a set, perform the removal operation, and convert the set back to an array.

Array code:

var timer = function(name) {
  var start = new Date();
  return {
    stop: function() {
      var end = new Date();
      var time = end.getTime() - start.getTime();
      console.log('Timer:', name, 'finished in', time, 'ms');
    }
  }
};

var getRandom = function(min, max) {
  return Math.random() * (max - min) + min;
};

var lastNames = ['SMITH', 'JOHNSON', 'WILLIAMS', 'JONES', 'BROWN', 'DAVIS', 'MILLER', 'WILSON', 'MOORE', 'TAYLOR', 'ANDERSON', 'THOMAS'];

var genLastName = function() {
  var index = Math.round(getRandom(0, lastNames.length - 1));
  return lastNames[index];
};

var sex = ["Male", "Female"];

var genSex = function() {
  var index = Math.round(getRandom(0, sex.length - 1));
  return sex[index];
};

var Person = function() {
  this.name = genLastName();
  this.age = Math.round(getRandom(0, 100))
  this.sex = "Male"
};

var genPersons = function() {
  for (var i = 0; i < 100000; i++)
    personArray.push(new Person());
};

var changeSex = function() {
  for (var i = 0; i < personArray.length; i++) {
    personArray[i].sex = genSex();
  }
};

var deleteMale = function() {
  for (var i = 0; i < personArray.length; i++) {
    if (personArray[i].sex === "Male") {
      personArray.splice(i, 1)
      i--
    }
  }
};

var t = timer("Array");

var personArray = [];

genPersons();

changeSex();

deleteMale();

t.stop();

console.log("Done! There are " + personArray.length + " persons.")

Set code:

var timer = function(name) {
    var start = new Date();
    return {
        stop: function() {
            var end  = new Date();
            var time = end.getTime() - start.getTime();
            console.log('Timer:', name, 'finished in', time, 'ms');
        }
    }
};

var getRandom = function (min, max) {
  return Math.random() * (max - min) + min;
};

var lastNames = ['SMITH','JOHNSON','WILLIAMS','JONES','BROWN','DAVIS','MILLER','WILSON','MOORE','TAYLOR','ANDERSON','THOMAS'];

var genLastName = function() {
    var index = Math.round(getRandom(0, lastNames.length - 1));
    return lastNames[index];
};

var sex = ["Male", "Female"];

var genSex = function() {
    var index = Math.round(getRandom(0, sex.length - 1));
    return sex[index];
};

var Person = function() {
	this.name = genLastName();
	this.age = Math.round(getRandom(0,100))
	this.sex = "Male"
};

var genPersons = function() {
for (var i = 0; i < 100000; i++)
	personSet.add(new Person());
};

var changeSex = function() {
	for (var key of personSet) {
		key.sex = genSex();
	}
};

var deleteMale = function() {
	for (var key of personSet) {
		if (key.sex === "Male") {
			personSet.delete(key)
		}
	}
};

var t = timer("Set");

var personSet = new Set();

genPersons();

changeSex();

deleteMale();

t.stop();

console.log("Done! There are " + personSet.size + " persons.")

2 of 7
94

OBSERVATIONS:

  • Set operations can be understood as snapshots within the execution stream.
  • We are not before a definitive substitute.
  • The elements of a Set class have no accessible indexes.
  • Set class is an Array class complement, useful in those scenarios where we need to store a collection on which to apply basic addition, Deletion, checking and iteration operations.

I share some test of performance. Try to open your console and copypaste the code below.

Creating an array (125000)

var n = 125000;
var arr = Array.apply( null, Array( n ) ).map( ( x, i ) => i );
console.info( arr.length ); // 125000

1. Locating an Index

We compared the has method of Set with Array indexOf:

Array/indexOf (0.281ms) | Set/has (0.053ms)

// Helpers
var checkArr = ( arr, item ) => arr.indexOf( item ) !== -1;
var checkSet = ( set, item ) => set.has( item );

// Vars
var set, result;

console.time( 'timeTest' );
result = checkArr( arr, 123123 );
console.timeEnd( 'timeTest' );

set = new Set( arr );

console.time( 'timeTest' );
checkSet( set, 123123 );
console.timeEnd( 'timeTest' );

2. Adding a new element

We compare the add and push methods of the Set and Array objects respectively:

Array/push (1.612ms) | Set/add (0.006ms)

console.time( 'timeTest' );
arr.push( n + 1 );
console.timeEnd( 'timeTest' );

set = new Set( arr );

console.time( 'timeTest' );
set.add( n + 1 );
console.timeEnd( 'timeTest' );

console.info( arr.length ); // 125001
console.info( set.size ); // 125001

3. Deleting an element

When deleting elements, we have to keep in mind that Array and Set do not start under equal conditions. Array does not have a native method, so an external function is necessary.

Array/deleteFromArr (0.356ms) | Set/remove (0.019ms)

var deleteFromArr = ( arr, item ) => {
    var i = arr.indexOf( item );
    i !== -1 && arr.splice( i, 1 );
};

console.time( 'timeTest' );
deleteFromArr( arr, 123123 );
console.timeEnd( 'timeTest' );

set = new Set( arr );

console.time( 'timeTest' );
set.delete( 123123 );
console.timeEnd( 'timeTest' );

Read the full article here

🌐
MeasureThat
measurethat.net › Benchmarks › Show › 7818 › 0 › sethas-vs-arrayincludes
Benchmark: set.has vs. array.includes - MeasureThat.net
convert to set + set.has vs. array.includes · Includes (array) vs Has (Set) set vs array find if exists · array.includes vs. set.has on the fly · Array includes vs Set.has · Comments · × · Do you really want to delete benchmark? Cancel Delete · × · FAQ: FAQ ·
🌐
Azurewebsites
benchmarklab.azurewebsites.net › Benchmarks › Show › 13477 › 0 › arrayincludes-vs-sethas-v3
Benchmark: Array.includes vs Set.has v3 - MeasureThat.net
✓ Set.has: 17,598,264 ops/sec · • Array.includes: 11,929 ops/sec · Results show median performance across all community submissions. Run this benchmark yourself to verify on your device. Rendered benchmark preparation results: Run tests (2) Previous results Fork ·
Find elsewhere
🌐
Jsperf
jsperf.app › pikuzu
Set.has() vs Array.includes()
Set.has() vs Array.includes() - Online Javascript Benchmark
🌐
Sergio Carracedo
sergiocarracedo.es › js-lists-performance
Sergio Carracedo | Find a item in lists in js: Performance of Set vs Array
September 4, 2023 - In most cases, we use simple arrays to store the data, and we use the includes method to check if a value is in the array or not.
🌐
Jsbench
jsbench.me › myjyq4ixs1 › 1
Array includes VS Object address VS Set has (version 1)
JSBench.me is a JavaScript performance benchmarking playground based on Benchmark.js and influenced by JSPerf.
🌐
Reddit
reddit.com › r/learnjavascript › i discovered set exists for the first time today... is it really faster?
r/learnjavascript on Reddit: I discovered Set exists for the first time today... Is it really faster?
July 24, 2024 -

I was working through a problem in Angular, and finally had all the data I wanted to process pieced together.

I am very curious whether Set() is a common thing these days and whether I should consider learning more about these ES6 operator even if nobody on my team has ever used them (I have the least experience by a mile).

My first instinct was to go for an array, but then I asked ChatGPT to help me finish up the code, and it switched to a Set(). When I asked why, it said Set() is faster and excludes duplicates from the array.

The task consisted of:

Array 1: An array of arrays (a ton of data inside them),
Array 2: An array of 2+ objects with some string properties
Array 3: An array of objects with about 90 objects in it

The purpose is:

  1. Loop through each object of Array 1 and find if the status string is what we want. If so we add the ID from that object to the targetId's Set().

  2. Use the list of 90 objects and check if the ID we added in Step 1 exists in an object somewhere in there

  3. If it exists in there, use the item.category to access the number value from categoryCounts object and increment it.

Here is a generic version of the code:

const categoryCounts: {
[category: string]: number
} = {};
// Extract IDs from the data
const targetIds = new Set < number > ();
const segments = [
...data.segmentOneArray,
...data.segmentTwoArray,
...data.segmentThreeArray,
...data.segmentFourArray,
];
segments.forEach((segment) => {
if (segment.status === "statusWeWant" && segment.itemId) {
targetIds.add(segment.itemId);
}
});
// Process the item list to count occurrences for each category
itemList.forEach(item => {
if (targetIds.has(Number(item.itemId))) {
const category = item.category;
if (filteredCategories.some(c => c.description === category)) {
if (!categoryCounts[category]) {
categoryCounts[category] = 0;
}
categoryCounts[category]++;
}
}
})

🌐
Jsbench
jsbench.me › myjyq4ixs1 › 2
Array includes VS Object address VS Set has (version 2) - JavaScript benchmark at JSBench.me
i += ary.includes(3333) && 1; i += ary.includes(1234) && 1; i += strAry.includes('x3333') && 1; i += strAry.includes('x1234') && 1;DEFER ... i += set.has(3333) && 1; i += set.has(1234) && 1; i += strSet.has('x3333') && 1; i += strSet.has('x1234') && 1;DEFER
🌐
MeasureThat
measurethat.net › Benchmarks › Show › 13803 › 0 › arrayincludes-vs-sethas-vas-maphas
Benchmark: Array.includes vs Set.has vas Map.has - MeasureThat.net
Array.includes vs Set.has vs Map.has vs Object in · Array.includes vs Set.has vas Map.has vs Object accessor · Array.includes vs Set.has vas Map retrive · Array.includes vs Set.has vas Map.has 2 · Comments · × · Do you really want to delete benchmark? Cancel Delete ·
Top answer
1 of 3
6

I know this is an old question, but I was double checking the data. I too assumed Set.has would be O(1) or O(log N), but in my first test, it appeared to be O(N). The specs for these functions hint as much, but are quite hard to decipher: https://tc39.es/ecma262/#sec-array.prototype.includes https://tc39.es/ecma262/#sec-set.prototype.has Elsewhere, though, they also say that Set.has must be sublinear-- and I believe modern implementations are.

Empirically, Set.has demonstrates linear performance when I ran it in some code playgrounds... but in real environments like node and chrome, they there were no surprises. I'm not sure what the playground was running on the back end, but perhaps a Set polyfill was used. So be careful!

Here's my test cases, trimmed down to remove the randomness:

const makeArray = (size) => [...Array(size)].map(() => size);

const small =  makeArray(1000000);
const medium = makeArray(10000000);
const large =  makeArray(100000000);

const solution1 = arr => {
  console.time('Array.includes');
  arr.includes(arr.length - 1)
  console.timeEnd('Array.includes');
}

const solution2 = arr => {
  const set = new Set(arr)
  console.time('Set.has');
  set.has(arr.length-1)
  console.timeEnd('Set.has');
}


console.log('** Testing small array:');
solution1(small);
solution2(small);
console.log('** Testing medium array:');
solution1(medium);
solution2(medium);
console.log('** Testing large array:');
solution1(large);
solution2(large);

In Chrome, though:

** Testing small array:
VM183:10 Array.includes: 1.371826171875 ms
VM183:17 Set.has: 0.005859375 ms
VM183:25 ** Testing medium array:
VM183:10 Array.includes: 14.32568359375 ms
VM183:17 Set.has: 0.009765625 ms
VM183:28 ** Testing large array:
VM183:10 Array.includes: 115.695068359375 ms
VM183:17 Set.has: 0.0048828125 ms

In Node 16.5:

Testing small array:
Array.includes: 1.223ms
Set.has: 0.01ms
Testing medium array:
Array.includes: 11.41ms
Set.has: 0.054ms
Testing large array:
Array.includes: 127.297ms
Set.has: 0.047ms

So, yeah, Arrays are definitionly linear, and Sets are much faster.

2 of 3
2

The comparison like that is not entirely fair because in the function where you use the Set, the Array needs to be converted to a Set first, which takes some time.

Have a look at the results below if this is ignored. I have updated the solution2 function to receive a Set and changed the while loop to a for loop - for the sake of direct comparison.

You may notice that for a small array, Set might be slower. This is trivial because the time complexity only really comes into affect for a large (significant) n.

Also note, Array.includes is indeed O(n) but because it is in a for loop which in the worst case could go up to n the solution has a time complexity of O(n^2).

const rand = (size) => [...Array(size)].map(() => Math.floor(Math.random() * size));

const small = rand(100);
const medium = rand(5000);
const large = rand(100000);

const solution1 = arr => {
  console.time('Array.includes');
  for (let int = 1;;int++) {
    if (!arr.includes(int)) {
      console.timeEnd('Array.includes');
      return int;
    }
  }
}

const solution2 = set => {
  console.time('Set.has');
  for (let i = 1;;i++) {
    if (!set.has(i)) {
      console.timeEnd('Set.has');
      return i
    }
  }
}

console.log('Testing small array:');
solution1(small);
solution2(new Set(small));
console.log('Testing medium array:');
solution1(medium);
solution2(new Set(medium));
console.log('Testing large array:');
solution1(large);
solution2(new Set(large));
Run code snippetEdit code snippet Hide Results Copy to answer Expand

🌐
Reddit
reddit.com › r/learnjavascript › am i wrong to think that the “has” method for sets is better for time complexity vs “includes” for arrays?
r/learnjavascript on Reddit: Am I wrong to think that the “has” method for Sets is better for time complexity vs “includes” for Arrays?
October 13, 2020 -

I had an interview where to avoid double looping, I created a Set and used the has method to avoid O(n2) within a for loop.

The interviewer said it would still be O(n2) and said I should think of a different way for O(n) complexity.

Code would have looked something like this, hoping it would still be linear:

let mySet = new Set(array);
for(let i = 0; i < array.length; i++) {
    if(mySet.has(i)) {
         // do stuff
    }
}

vs. using inlcudes for arrays which I believe would be O(n2)

for(let i = 0; i < array.length; i++) {
    if(array.includes(i)) {
         // do stuff
    }
}
🌐
Jsben
jsben.ch › array.includes-vs-set.has-z5muv
Array.includes vs Set.has - JSBEN.CH JavaScript Benchmark
In this test, the performance of checking for element existence in an array using 'Array.includes' is compared against checking in a set using 'Set.has'.
🌐
Azurewebsites
benchmarklab.azurewebsites.net › Benchmarks › Show › 8768 › 0 › sethas-vs-arrayincludes-vs-arrayindexof-string-values
Benchmark: set.has vs. array.includes vs array.indexOf (string values) - MeasureThat.net
includes · 54.5M/s · View exact numbers · LLMs can make mistakes. Check important info. set.has vs. array.includes (string values) set.has vs. array.includes (random string values) set.has vs. array.includes vs array.indexOf (string values) - longer · set.add vs array.push maan ·
🌐
Rune Hub
rune.codes › home › tutorials › javascript › set vs array in javascript: complete guide
Set vs Array in JavaScript: Which to Use and When | Rune Hub
July 15, 2026 - Set's has() checks membership in roughly constant time, no matter how large the collection gets. Array's includes() has to scan from the beginning until it finds a match or reaches the end:
🌐
Medium
medium.com › @itshim.1510 › map-vs-set-vs-array-includes-2bf326e6f81e
Map vs Set vs Array.includes. Have you ever considered about the… | by Himanshu Mishra | Medium
August 28, 2019 - With the same data set, the execution time came around 0.96 ms. So clearly, Array.includes was much faster in execution than Map although Map data structure uses hash maps.