手写Map

89 阅读2分钟

首先介绍下Map

相关链接可以看阮一峰的es6

Map定义:本质上是键值对的集合(Hash 结构)

Map常用方法

  • set 设置keyvalue
  • get 获取key
  • has 判断是否存在对应key
  • delete 删除对应key
  • size 获取Map的长度
  • clear 清除所有成员

Map 的遍历方法

  • Map.prototype.keys():返回键名的遍历器。
  • Map.prototype.values():返回键值的遍历器。
  • Map.prototype.entries():返回所有成员的遍历器。
  • Map.prototype.forEach():遍历 Map 的所有成员。

类型转换

  • 转化为数组:扩展运算符[...myMap]
  • 数组转为Map:new Map
  • 转化为对象:Object.create+for
  • 对象转化为Map:new Map(Object.entries(obj))

Map和Object性能对比

        let obj={};

        let map=new Map();
        function each(cb){
            for(let i=0;i++;i<1000000){
              cb(i+'_',i)
            }
        }
        //object遍历
        console.time('obj');
        //添加
        each((key,value)=>{
            obj[key]=value;
        })
        each((key,value)=>{
             delete obj[key];
        })
        console.timeEnd('obj');
    
        // //object遍历
        // console.time('map');
        // //添加
        // each((key,value)=>{
        //     map.set(key,value);
        // })
        // each((key,value)=>{
        //     map.delete(key);
        // })
        // console.timeEnd('map');

        //

经测试Map增删10万条数据,性能优于obj的

image.png

image.png

平均上还是优于obj的

手写Map

实现功能

        const map=new MyMap();
        map.set(1,'a');
        map.set(9,'pppp')
        map.set(2,'pp')
        console.log(map)
        console.log(map.get(1));
        console.log(map.get(9));

        console.log(map.has(1));
        console.log(map.has(3));

实现

        //模拟实现hash的底数
        const maxLength=8;
        function MyMap(){
            //创建一个数组长度为8
            的数组
            this.store=new Array(maxLength);
            //遍历数组,每一个数组的value都设置为空链表形式
            for(let i=0;i<this.store.length;i++){
                this.store[i]={
                    next:null
                }              
            }
        }
        //简单模拟hash值
        MyMap.prototype.hash=function(k){
            return k%maxLength;
        }
        MyMap.prototype.has=function(k){
            this.hasKey=false;
            this.get(k);
            return this.hasKey

        }
        MyMap.prototype.get=function(k){
          let roomIndex=this.hash(k);
          let quene=this.store[roomIndex];
          //跳过空链表头
          quene=quene.next;
          while(quene){
            if(quene.key===k){
               //辅助has的方法
                this.hasKey=true;
                return quene.value
            }else{
                //往下移动
                quene=quene.next;
            }
          }
          return undefined;
        }
        //设置key,value
        MyMap.prototype.set=function(k,v){
            //获取对应key的房间索引
            let roomIndex=this.hash(k);
            //找到这个房间对应的链表
            let quene=this.store[roomIndex];
            console.log(quene)
            //判断链表的next是否存在
            while(quene.next){
                //如果当前的next的key等于k;重写当前的key
                if(quene.next.key===k){
                     quene.next.value=v
                }else{
                    //如果当前没找到;队列往下移动准找
                    quene=quene.next;
                }
            }
            //不存在,直接将当前的值赋值给quene.next
            quene.next={
                key:k,
                value:v,
                next:null
            }

        }