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需要以某种方式获取它的键然后才能迭代。
性能 在频繁增删键值对的场景下表现更好。 在频繁添加和删除键值对的场景下未作出优化。

JS数据结构之 Map的更多相关文章

  1. JS中的 map, filter, some, every, forEach, for in, for of 用法总结和区别

    JS中的 map, filter, some, every, forEach, for in, for of 用法总结和区别  :https://blog.csdn.net/hyupeng1006/a ...

  2. Javascript 如何生成Less和Js的Source map

    为什么有Source map CSS和JS脚本正变得越来越复杂,为了解决网络瓶颈,大部分源代码都需要经过编译.合并.压缩才能运用到实际环境中.为了减少网络资源占用,源码一般都会经过以下方式处理: 使用 ...

  3. ES6 之 Set数据结构和Map数据结构 Iterator和for...of循环

    ECMAScript 6 入门 Set数据结构 基本用法 ES6提供了新的数据结构Set.它类似于数组,但是成员的值都是唯一的,没有重复的值. Set本身是一个构造函数,用来生成Set数据结构. va ...

  4. 原生JS forEach()和map()遍历的区别以及兼容写法

    一.原生JS forEach()和map()遍历 共同点: 1.都是循环遍历数组中的每一项. 2.forEach() 和 map() 里面每一次执行匿名函数都支持3个参数:数组中的当前项item,当前 ...

  5. js实现的map方法

    /** * * 描述:js实现的map方法 * @returns {Map} */ function Map(){ var struct = function(key, value) { this.k ...

  6. echarts.js应用之map

    最近项目中用到了echarts.js中的map,我画了一个简版的案例,如下所示: 效果图: 主要代码如下: <!DOCTYPE html> <html lang="en&q ...

  7. js中的Map对象的简单示例

    es6提供一个对象Map, 其功能类似于java中的Map, 下面是java中的Map和js中的Map的简单对比: js中的Map.set()相当于java中的Map.put(), js中的Map.s ...

  8. 原生JS forEach()和map()遍历,jQuery$.each()和$.map()遍历

    一.原生JS forEach()和map()遍历 共同点: 1.都是循环遍历数组中的每一项. 2.forEach() 和 map() 里面每一次执行匿名函数都支持3个参数:数组中的当前项item,当前 ...

  9. JS数据结构第三篇---双向链表和循环链表之约瑟夫问题

    一.双向链表 在上文<JS数据结构第二篇---链表>中描述的是单向链表.单向链表是指每个节点都存有指向下一个节点的地址,双向链表则是在单向链表的基础上,给每个节点增加一个指向上一个节点的地 ...

随机推荐

  1. Linux YUM yum 命令详解

    Yum命令 常用yum命令列表 command is one of: * install package1 [package2] [...] * update [package1] [package2 ...

  2. 记一次 .NET 某工控数据采集平台 线程数 爆高分析

    一:背景 1. 讲故事 前几天有位朋友在 B站 加到我,说他的程序出现了 线程数 爆高的问题,让我帮忙看一下怎么回事,截图如下: 说来也奇怪,这些天碰到了好几起关于线程数无缘无故的爆高,不过那几个问题 ...

  3. ArrayList集合概述和基本使用和ArrayList集合的常用方法和遍历

    什么是ArrayList类 java.util.ArrayList 是大小可变的数组的实现,存储在内的数据称为元素.此类提供一些方法来操作内部存储 的元素. ArrayList 中可不断添加元素,其大 ...

  4. Solution -「HNOI2013」消毒

    弱化一下,先考虑在二维上解决问题. 题目就转化为:有 \(n\) 个点 \((i, j)\) 需要被覆盖,而我们每次可以选一行或一列去覆盖,求覆盖所有点的最少选择次数. 如果我们对于每一个 \((i, ...

  5. 苹果手机和Windows之间互传文件

    参考链接:https://jingyan.baidu.com/article/a378c960c46804f229283064.html 实现原理:就是使用Samba服务,windows共享一个文件夹 ...

  6. Unity3D学习笔记9——加载纹理

    目录 1. 概述 2. 详论 2.1. Resources方式 2.2. API方式 2.3. Web方式 1. 概述 理论上,Unity中加载纹理并没有什么难度,只需要将图片放置在Assets文件夹 ...

  7. 重写Object的equals方法和Objects的equals方法

    Object类的equals方法默认比较的是两个对象的地址值,没有意义 所以我们需要重写equals方法,比较两个对象的属性值(name,age等等): 对象的属性值一样返回true否则返回false ...

  8. 国产钡铼分布式IO模块如何与西门子PLC Profinet通讯

    1.准备IO模块:耦合器BL200PN.数字量输出模块M2082.数字量输入M1081.模拟量输入模块M3401.模拟量输出M4043. 编辑搜图 请点击输入图片描述(最多18字) ​2.BL200P ...

  9. 什么是双网口以太网IO模块

    MXXXE系列远程IO模块工业级设计,适用于工业物联网和自动化控制系统,MxxxE工业以太网远程 I/O 配备 2 个mac层数据交换芯片的以太网端口,允许数据通过可扩展的菊花链以太网远程 I/O 阵 ...

  10. 四位一体水溶交融,Docker一拖三Tornado6.2 + Nginx + Supervisord非阻塞负载均衡容器式部署实践

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_203 容器,又见容器.Docker容器的最主要优点就在于它们是可移植的.一套服务,其所有的依赖关系可以捆绑到一个独立于Linux内 ...