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需要以某种方式获取它的键然后才能迭代。 |
| 性能 | 在频繁增删键值对的场景下表现更好。 | 在频繁添加和删除键值对的场景下未作出优化。 |
JS数据结构之 Map的更多相关文章
- 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 ...
- Javascript 如何生成Less和Js的Source map
为什么有Source map CSS和JS脚本正变得越来越复杂,为了解决网络瓶颈,大部分源代码都需要经过编译.合并.压缩才能运用到实际环境中.为了减少网络资源占用,源码一般都会经过以下方式处理: 使用 ...
- ES6 之 Set数据结构和Map数据结构 Iterator和for...of循环
ECMAScript 6 入门 Set数据结构 基本用法 ES6提供了新的数据结构Set.它类似于数组,但是成员的值都是唯一的,没有重复的值. Set本身是一个构造函数,用来生成Set数据结构. va ...
- 原生JS forEach()和map()遍历的区别以及兼容写法
一.原生JS forEach()和map()遍历 共同点: 1.都是循环遍历数组中的每一项. 2.forEach() 和 map() 里面每一次执行匿名函数都支持3个参数:数组中的当前项item,当前 ...
- js实现的map方法
/** * * 描述:js实现的map方法 * @returns {Map} */ function Map(){ var struct = function(key, value) { this.k ...
- echarts.js应用之map
最近项目中用到了echarts.js中的map,我画了一个简版的案例,如下所示: 效果图: 主要代码如下: <!DOCTYPE html> <html lang="en&q ...
- js中的Map对象的简单示例
es6提供一个对象Map, 其功能类似于java中的Map, 下面是java中的Map和js中的Map的简单对比: js中的Map.set()相当于java中的Map.put(), js中的Map.s ...
- 原生JS forEach()和map()遍历,jQuery$.each()和$.map()遍历
一.原生JS forEach()和map()遍历 共同点: 1.都是循环遍历数组中的每一项. 2.forEach() 和 map() 里面每一次执行匿名函数都支持3个参数:数组中的当前项item,当前 ...
- JS数据结构第三篇---双向链表和循环链表之约瑟夫问题
一.双向链表 在上文<JS数据结构第二篇---链表>中描述的是单向链表.单向链表是指每个节点都存有指向下一个节点的地址,双向链表则是在单向链表的基础上,给每个节点增加一个指向上一个节点的地 ...
随机推荐
- .NET ORM框架HiSql实战-第一章-集成HiSql
一.引言 做.Net这么多年,出现了很多很多ORM框架,比如Dapper,Sqlsugar,Freesql等等.在之前的项目中,用到的ORM框架也大多数是这几个老牌的框架. 不过最近园子关于.NET ...
- C4C UI Design背景色
- 聊聊Netty那些事儿之从内核角度看IO模型
从今天开始我们来聊聊Netty的那些事儿,我们都知道Netty是一个高性能异步事件驱动的网络框架. 它的设计异常优雅简洁,扩展性高,稳定性强.拥有非常详细完整的用户文档. 同时内置了很多非常有用的模块 ...
- Burnside 引理与 Pólya 定理
群 群的定义 在数学中,群是由一种集合以及一个二元运算所组成的,符合"群公理"的代数结构. 一个群是一个集合 \(G\) 加上对 \(G\) 的二元运算.二元运算用 \(\cdot ...
- 类似Tower的而故事还没结束
我对于SaaS一种有一种英雄主义的情怀在里面,无论是早期的推事本,还是后面我去调研的麦客CRM,国内的SaaS都在努力生长,在后疫情时代剩下的都是平台级的钉钉.飞书,或者垂直领域的王炸app了. 我早 ...
- Webpack干货系列 | 怎么运用 Webpack 5 处理css/scss/sass、less、stylus样式资源
程序员优雅哥简介:十年程序员,呆过央企外企私企,做过前端后端架构.分享vue.Java等前后端技术和架构. 本文摘要:主要讲解webpack 5 如何高效处理CSS 资源.scss/sass 资源.l ...
- jdbc 11: 封装自己的jdbc工具类
jdbc连接mysql,封装自己的jdbc工具类 package com.examples.jdbc.utils; import java.sql.*; import java.util.Resour ...
- CF1703C Cypher 题解
题意:模拟一个 \(n\) 位密码锁. 做法:直接模拟,注意往后推,即若为 \(U\) 变为 \(D\),若为 \(D\) 变为 \(U\).注意 \(0\) 和 \(9\) 进行操作时的特判. #i ...
- 操作表查询&操作表创建&操作表删除&操作表修改
2.操作表 C(create):创建 语法: create table 表明( 列名1 数据类型1, 列名2 数据烈性2, .... 列名n 数据类型n ); create table Student ...
- Junit使用步骤和junit_@Before&@After
测试: 1.定义一个测试类(测试用例) 建议: 测试类名:被测试的类型Test CalculatorTest 包名:xxx.xxx.xx.test com.li.Test 2.定义测试方法:可以独立运 ...