console.time("set")
var s = new Set()
for(var i = 0; i < 10000; i++)
s.add(Math.random())
s.forEach(function(e){
s.delete(e)
})
console.timeEnd("set")
console.time("array")
var s = new Array()
for(var i = 0; i < 10000; i++)
s.push(Math.random())
s.forEach(function(e,i){
s.splice(i)
})
console.timeEnd("array")
对于测试的这一部分,我使用 for循环来迭代数组,使用 for of循环来迭代集合。同样,在数组上迭代更快。这一次似乎是指数级的,因为在“小”测试中花费的时间是指数级的两倍,在“大”测试中花费的时间几乎是指数级的四倍。
从集合中移除元素
这才是有趣的地方。我使用了 for循环和 .splice的组合来从数组中删除一些元素,并使用了 for of和 .delete来从集合中删除一些元素。对于“小”测试,从集合中移除项目的速度要快3倍(2.6毫秒 vs 7.1毫秒) ,但是对于“大”测试,情况发生了巨大的变化: 从数组中移除项目需要1955.1毫秒,而从集合中移除项目只需要83.6毫秒,快23倍。
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.")
设置代码:
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.")
对于问题的迭代部分,我最近运行了这个测试,发现 Set 的性能远远超过10,000个项目的 Array (大约10倍的操作可以在同一时间段内进行)。并且取决于浏览器是否在 like for like test 中击败或丢失 Object.hasOwnProperty。另一个有趣的地方是 Object 没有官方保证的顺序,而 JavaScript 中的 Set是作为 OrderedSet 实现的,并且确实维护插入顺序。
Set 和 Object 都有他们的“ has”方法,看起来分摊到 O (1) ,但是取决于浏览器的实现,一个操作可能需要更长或更快的时间。似乎大多数浏览器在 Object 中实现键的速度都快于 Set.has ()。即使 Object.hasOwnProperty 包含对密钥的额外检查,也比 Set.has ()快5% 左右,至少对我在 Chrome v86上是这样。