跳到主要内容

Map 和 Set-有序和无序

有序和无序,先看个例子

<p class="container" style="color: red" id="p1">
<img src="xxx" alt="xxx.png">
<span>123</span>
</p>
<script>
// vdom 虚拟 dom - 模拟真是的 dom 结构
const p = {
tag: 'p',
props: { // 无序
id: 'p1',
className: 'container',
style: 'color:red'
},
children: [ // 有序
{
tag: 'img',
props: {
alt: 'xxx',
src: 'xxx.png'
}
},
{
tag: 'span',
children: [123]
}
]
}
// js 中 Object 是无序的,Array 是有效的
</script>
  • 有序:操作慢
  • 无序:操作快,但无序
  • 如何结合两者优点呢? - 二叉树、及其变种

Map 和 Object 的区别

  • API 不同,Map 可以以任意类型为 key
  • Map 是有序结构(重要)
  • Map 操作同样很快
const obj1 = {
2: 'hello',
1: {x: 100},
3: 100,
}

// Object 是无序的
console.log(Object.keys(obj1)) // ['1', '2', '3']

// Object 有多快?
for (let i = 0; i < 1000 * 10000; i++) {
obj1[i + ''] = i
}
console.time('obj find')
obj1['2000000']
console.timeEnd('obj find') // obj find: 0.0068359375 ms

// Map Api: set,delete,has,forEach,size
const m = new Map([
['key1', 'hello'],
['key3', {x: 100}],
['key2', 100],
])

// Map 的 key 可以为任意类型
const obj2 = {name: 'xxx'}
m.set(obj2, 'object key')

function fn() {
}

m.set(fn, 'fn key')

// 比如 obj1 和 obj2 关联,但是没有引用关系,保持独立
// m.set(obj1, obj2)

// Map 是有序的
m.forEach((value, key) => console.log(key, value)) // 保持顺序输出

// Map 有多快?
for (let i = 0; i < 1000 * 10000; i++) {
m.set(i + '', i)
}
console.time('map find')
m.has('2000000')
console.timeEnd('map find') // map find: 0.01416015625 ms

Set 和 Array 的区别

  • API 不同
  • Set 元素不能重复
  • Set 是无序结构,操作很快
const arr = [1, 2, 3, 4]
const set = new Set([1, 2, 2, 3, 4])

// Map Api: add,delete,has,forEach,
set.forEach(val => console.log(val))

// Set 元素是不能重复的(数组去重)
console.log(set) // Set(4){1, 2, 3, 4}

// Set 是无序的(快),arr 是有序的(慢)
for (let i = 0; i < 100 * 10000; i++) {
arr.push(i)
}
console.time('arr unshift')
arr.unshift('a') // 导致所有元素后移,所以慢
console.timeEnd('arr unshift') // arr unshift: 0.25390625 ms
console.time('arr push')
arr.push('b')
console.timeEnd('arr push') // arr push: 0.005859375 ms
console.time('arr find')
arr.includes('20000')
console.timeEnd('arr find') // arr find: 0.89794921875 ms

for (let i = 0; i < 100 * 10000; i++) {
set.add(i)
}
console.time('set add')
set.add('a')
console.timeEnd('set add') // set add: 0.00390625 ms
console.time('set find')
set.has('20000')
console.timeEnd('set find') // set find: 0.005859375 ms