手写Map

ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。

我们先使用下Map

let map = new Map()

    map.set(1, 'a')
    map.set(2, 'b')
    map.set(3, 'c')
    console.log(map) // 
        // [[Entries]]
        // [{1 => "a"}
        // {2 => "b"}
        // {3 => "c"}]
    console.log(map.get(1)) //a

    console.log(map.has(2)) // true
    console.log(map.has(9)) // false

    map.delete(1) // 删除1

我们打印出来的 Map 是一个键值对组成的伪数组,所以我们就可以这样

遍历


    for (let entries of map) {
        console.log(entries)
            /** (2) [1, 'a']
                (2) [2, 'b']
                (2) [3, 'c']*/
    }

转数组

Array.from(map) //  [[1, 'a'],[2, 'b'],[3, 'c']]

转对象

Object.fromEntries(map) // {1: 'a', 2: 'b', 3: 'c'}

Map原理

        在 Object 中, key 必须是简单数据类型(整数,字符串或者是 symbol),而在 Map 中则可以是 JavaScript 支持的所有数据类型,也就是说可以用一个 Object 来当做一个Map元素的 key。

        Map存值会通过hash算法,根据不同的键放到数组的8个不同的房间(因为字节的最小单位 1byte = 8 bit)。每个房间里面是一个链表,新增,删除会快一点。也就是说Map相对于Object来说,会比Object操作快一些(其实快的也不是很多,数据不是很多可以忽略)。

 手写实现代码

 // 手写Map
    class MyMap {

        constructor() {
            this.count = 8
            this.store = []
            this.initStore()
        }

        // 初始化
        initStore() {

            // 每个房间是一个链表,所以先创建一个表头
            for (let i = 0; i < 8; i++) {
                this.store[i] = {
                    next: null
                }
            }
        }


        // 修改
        set(k, v) {
            // 通过K获取房间号 
            let index = this.hash(k)
                // 获取标头
            let top = this.store[index]

            // 判断有没有这个k, 有替换 没有修改
            while (top.next) {
                if (top.key === k) {
                    top.value = v
                } else {
                    // 如果没有找到就 下一个
                    top = top.next
                }
            }

            // 如果没有找到 就是新增
            top.next = {
                next: null,
                key: k,
                value: v
            }
        }

        // 获取
        get(k) {
            // 通过K获取房间号 
            let index = this.hash(k)
                // 获取标头
            let top = this.store[index].next // 跳过表头

            while (top) {
                if (top.key === k) {
                    return top.value
                } else {
                    // 如果没有找到就 下一个
                    top = top.next
                }
            }

            // 如果没有找到就
            return undefined
        }

        // 根据键去匹配房间,底层不是这么简单,我们这里简单处理下
        hash(k) {
            return k % this.count
        }

        delet(k){
           // 以后加
        }

        // 是否存在
        has(k) {
            return this.get(k) === !undefined
        }
    }


    let map = new MyMap()

    map.set(1, "a")
    map.set(2, "b")
    map.set(3, "c")
    map.set(4, "d")
    map.set(5, "e")
    map.set(6, "f")
    map.set(7, "g")
    map.set(8, "h")
    map.set(9, "i")

    console.log(map.get(2)) // b

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值