这是我参与8月更文挑战的第2天,活动详情查看: 8月更文挑战
背景
今天看到一道力扣题时发现频繁操作键值对时使用Map比Object性能更优,于是简单测试了一下两者的区别。
结论
先上结论:
性能区别
- 当key为有序连续的整数时,Object的性能优于Map;(V8对Object在键为有序连续正整数时做了优化)
- 当key为字符串、非有序连续整数、Symbol时Map的 添加 和 读取 性能优于Object,修改 和 删除 操作性能相差不大;(Object会把键转为String类型,消耗了一部分性能)
- 当key为其他数据类型时,只能选择Map;(Object的键只能为string、symbol类型)
其他区别
- Object可以通过多种方式
(字面量、new Object()、Object.create()等)
创建,其中字面量的方式方便快捷。Map只能通过构造函数方式创建;- Map本身具有size属性,Object需要使用 keys()、values()等方法获取;
- Map本身具有可迭代属性,Object不具有;
- Map会保持数据的插入顺序,Object不会;
过程
看完了结论再来看看测试的过程, 先测试key为String时两者的区别
function createRandomKey() {
return new Date().getTime().toString().substr(6, 7) + '-' + (Math.random() * 100000000).toString().substr(0, 7);
}
let keys = []
function setKeys() {
for (let i = 0; i < 1000000; i++) {
keys.push(createRandomKey())
}
}
setKeys()
let obj = new Object()
let map = new Map()
function getObjectTimeDiff() {
let t1 = new Date().getTime()
for (let i in keys) {
obj[keys[i]] = i
}
let t2 = new Date().getTime()
for (let j in keys) {
let value = obj[keys[j]]
}
let t3 = new Date().getTime()
for (let k in keys) {
obj[keys[k]] = keys[k]
}
let t4 = new Date().getTime()
for (let l in keys) {
delete obj[keys[l]]
}
let t5 = new Date().getTime()
return `object 增:${t2 - t1},读:${t3 - t2},改:${t4 - t3},删:${t5 - t4}`
}
function getMapTimeDiff() {
let t1 = new Date().getTime()
for (let i in keys) {
map.set(keys[i], i)
}
let t2 = new Date().getTime()
for (let j in keys) {
let value = map.get(keys[j])
}
let t3 = new Date().getTime()
for (let k in keys) {
map.set(keys[k], keys[k])
}
let t4 = new Date().getTime()
for (let l in keys) {
map.delete(keys[l])
}
let t5 = new Date().getTime()
return `map 增:${t2 - t1},读:${t3 - t2},改:${t4 - t3},删:${t5 - t4}`
}
console.log(getObjectTimeDiff())
console.log(getMapTimeDiff())
我们多次执行会得到大概如下的数据(会因执行环境不同得到不同数据),可以明显看出Map在新增键值、读取键值时耗时低于Object
第一次执行
object 增:1121,读:710,改:339,删:397
map 增:545,读:220,改:453,删:491
第二次执行
object 增:1145,读:702,改:330,删:396
map 增:542,读:241,改:468,删:510
第三次执行
object 增:1153,读:707,改:359,删:403
map 增:546,读:237,改:465,删:507
第四次执行
object 增:1138,读:697,改:333,删:387
map 增:542,读:248,改:451,删:444
...
再修改代码,将keys改为下标的的集合,测试key为连续的整数时
function setKeys() {
for (let i = 0; i < 1000000; i++) {
keys.push(i)
}
}
多次执行
第一次执行
object 增:256,读:140,改:134,删:234
map 增:419,读:192,改:294,删:432
第二次执行
object 增:234,读:137,改:136,删:232
map 增:412,读:186,改:283,删:425
第三次执行
object 增:254,读:139,改:130,删:227
map 增:411,读:181,改:296,删:430
第四次执行
object 增:262,读:140,改:135,删:241
map 增:421,读:205,改:309,删:459
...
可以看到,在连续整数作为key时,Object的性能优于Map