JS数据结构之 Map

JS数据结构之 Map

Map介绍

Map(映射)是ES6引入的一种数据结构。这是一种存储键值对列表很方便的方法,类似于其他编程语言的哈希表。

HashMap(哈希表),也叫做散列表。是根据关键码值 key -> value而直接进行访问的数据结构。它通过把关键码值映射到表中一个位置来访问记录,有一点儿类似数组,但能以O(1)的时间复杂度查找到元素。

JS的对象Object,本质上是键值对的集合(Hash结构),但是传统上只能用字符串当作键,给使用带来了很大的限制。为了解决这个限制,ES6引入了Map的数据结构,它类似于对象,也是键值对的集合,但是键的范围不仅仅局限于字符串,而是各种类型的值(包括对象)都可以当作键,是一种更加完善的Hash结构的实现。


常用的Map方法有:

赋值 set(key, value)

获取 get(key)

移除指定键名及其对应的值 delete(key)

判断是否存在 has(key)

获取所有值 values()

key/value 迭代器 entries()

清空所有键值对 clear()


Map的数据转换:

Map转为数组:

const map_test = new Map();
console.log([...map_test]);

Map转为对象:

function mapToObj(map) {
    const obj = Object.create(null);
    map.forEach((v,k)=>{
        obj[k] = v;
    });
    return obj;
}
const map_test = new Map();
console.log(mapToObj(map_test));

Map转为JSON

function mapToObj(map) {
    const obj = Object.create(null);
    map.forEach((v,k)=>{
        obj[k] = v;
    });
    return obj;
}

function mapToJson(map){
    return JSON.stringify(mapToObj(map));
}

const map_test = new Map();
console.log(mapToJson(map_test));

对象转为Map

const object_test = {}
console.log(new Map(Object.entries(page_info))); 

数组转Map

const array_test = new Array();
console.log(new Map(array_test));

HashMap 和 Array 有什么区别?

查找效率:

  • HashMap因为是根据hashcode的值直接算出来index,所以查找效率是随着长度的增大而增加的。
  • ArrayMap使用的是二分法查找,所以当数组长度每增加一倍的时候,就需要多进行一次判断,效率下降。

扩容数量:

  • HashMap初始值16个长度,每次扩容的时候,直接申请双倍的数组空间
  • ArrayMap每次扩容的时候,如果size长度大于8时申请size*1.5个长度,大于4小于8时申请8个,小于4时申 请4个。这样比较ArrayMap其实是申请了更少的内存空间,但是扩容的频率会更高。因此,如果数据量比较大的时候,还是使用HashMap更合适,因为其扩容的次数要比ArrayMap少很多。

扩容效率:

  • HashMap每次扩容的时候重新计算每个数组成员的位置,然后放到新的位置。
  • ArrayMap则是直接使用System.arraycopy,所以效率上肯定是ArrayMap更占优势。

内存消耗:

  • 以ArrayMap采用了一种独特的方式,能够重复的利用因为数据扩容而遗留下来的数组空间,方便下一个ArrayMap的使用。而HashMap没有这种设计。 由于ArrayMap之缓存了长度是4和8的时候,所以如果频繁的使用到Map,而且数据量都比较小的时候,ArrayMap无疑是相当的是节省内存的。

总结:

综上所述,数据量比较小,并且需要频繁的使用Map存储数据的时候,推荐使用ArrayMap。 而数据量比较大的 时候,则推荐使用HashMap。


HashMap 和 Object 有什么区别?

Objects和Maps它们都允许你按键存取一个值、删除键、检测一个键是否绑定了值。

因此(并且也没有其他内建的替代方式了)过去我们一直都把对象当成Maps使用。

不过Maps和Objects有一些重要的区别,在下列情况里使用Map会是更好的选择:

Map Object
意外的键 Map默认情况不包含任何键。只包含显式插入的键。 一个Object有一个原型, 原型链上的键名有可能和你自己在对象上的设置的键名产生冲突。注意: 虽然 ES5 开始可以用Object.create(null)来创建一个没有原型的对象,但是这种用法不太常见。
键的类型 一个Map的键可以是任意值,包括函数、对象或任意基本类型。 一个Object的键必须是一个 String 或是Symbol。
键的顺序 Map中的 key 是有序的。因此,当迭代的时候,一个Map对象以插入的顺序返回键值。 一个Object的键是无序的注意:自ECMAScript 2015规范以来,对象确实保留了字符串和Symbol键的创建顺序; 因此,在只有字符串键的对象上进行迭代将按插入顺序产生键。
Size Map的键值对个数可以轻易地通过size 属性获取 Object的键值对个数只能手动计算
迭代 Map是 iterable 的,所以可以直接被迭代。 迭代一个Object需要以某种方式获取它的键然后才能迭代。
性能 在频繁增删键值对的场景下表现更好。 在频繁添加和删除键值对的场景下未作出优化。
posted @ 2022-08-24 09:01  笔下洛璃  阅读(1470)  评论(0编辑  收藏  举报