一文搞懂Map與Set的用法和區(qū)別解析
前言
作為前端開發(fā)人員,我們最常用的一些數(shù)據(jù)結(jié)構(gòu)就是 Object
、Array
之類的,畢竟它們使用起來非常的方便。往往有些剛?cè)腴T的同學(xué)都會忽視 Set
和 Map
這兩種數(shù)據(jù)結(jié)構(gòu)的存在,因?yàn)槟苡?set
和 map
實(shí)現(xiàn)的,基本上也可以使用對象或數(shù)組實(shí)現(xiàn),而且還更簡單。
但是,存在必然合理,當(dāng)你真正了解 Map
和 Set
之后,你就會發(fā)現(xiàn)它們原來時(shí)如此美好!
1.基本概念
我們先來了解以下 Map
和 Set
的基本概念,這樣才能幫助我們更好的使用。雖然我們通常把這兩種數(shù)據(jù)結(jié)構(gòu)混合著來講,但事實(shí)上它們它們還是有挺大區(qū)別的!
1.1 Map(字典)
想要迅速了解一個(gè)新的數(shù)據(jù)結(jié)構(gòu)或 API
是,查看官網(wǎng)是一個(gè)不錯(cuò)的選擇。Map
在官網(wǎng)上也有解釋,我們一起來看下。
官網(wǎng)解釋:
Map
對象保存鍵值對,并且能夠記住鍵的原始插入順序。任何值(對象或者原始值)都可以作為一個(gè)鍵或一個(gè)值。
官網(wǎng)的這句話非常精煉,我們從上面這句話中總結(jié)如下幾個(gè)關(guān)鍵詞:
- 鍵值對
- 記住插入順序
- 任意值作為鍵
一看到鍵值對,難免會想到對象。事實(shí)確實(shí)如此,Map
與我們平常所用的對象非常類似,它是一種類對象的數(shù)據(jù)結(jié)構(gòu),所以我們通常稱它為 Map
對象。
但是我們可以把它說得更為官方一點(diǎn):Map 字典。關(guān)于程序中字典的概念大家可以下去了解一下。
特點(diǎn)總結(jié):
Map
對象這種數(shù)據(jù)結(jié)構(gòu)和和對象類型,都已鍵值對的形式存儲數(shù)據(jù),即key-vlue
形式。Map
對象存儲的數(shù)據(jù)是有序的,而我們平常使用的對象是無序的,所以通常當(dāng)我們需要使用對象形式(鍵值對)存儲數(shù)據(jù)且需要有序時(shí),采用Map
對象進(jìn)行存儲。Map
對象的鍵值可以是任意類型,我們平時(shí)使用的對象只能使用字符串作為鍵。
1.2 Set(集合)
和 Map
類似,我們同樣先來看一看官網(wǎng)是怎么解釋 Set
這個(gè)數(shù)據(jù)結(jié)構(gòu)的。
官網(wǎng)的解釋:
Set 對象允許你存儲任何類型的唯一值,無論是原始值或者是對象引用。
Set
的解釋比 Map
的解釋還要精煉,我們從中提取出幾個(gè)關(guān)鍵詞:
- 任何類型
- 唯一值
上面關(guān)鍵詞中我們需要重點(diǎn)關(guān)注“唯一值”,這說明使用 Set
存儲的數(shù)據(jù)是不會重復(fù)的,除此之外,Set
也是一個(gè)對象,但是它是一個(gè)類數(shù)組對象,也就是說它長得像數(shù)組,我們通常直接稱它為 Set
對象。
當(dāng)然也可以官方一點(diǎn)的稱它:Set
集合。
特點(diǎn)總結(jié):
Set
對象是一個(gè)類數(shù)組對象,它長得就很像數(shù)組。Set
對象存儲的值是不重復(fù)的,所以我們通常使用它來實(shí)現(xiàn)數(shù)組去重。Set
對象存儲的數(shù)據(jù)不是鍵值對的形式,而且它可以存儲任何類型的數(shù)據(jù)。
2.基本使用
我們平常使用 Array
或者 Object
的時(shí)候,都是直接采用[變量] = []
、[變量] = {}
的形式來進(jìn)行初始化。而這里我們所講的 Map
和 Set
數(shù)據(jù)結(jié)構(gòu)它們都是以構(gòu)造函數(shù)的形式出現(xiàn)的,所以我們通常使用 new Set()
或者 new Map()
的形式初始化的。
2.1 Map 基本使用
初始化 map
對象:
let myMap = new Map();
初始化 map
時(shí)傳入數(shù)據(jù):
由于 Map
對象是一個(gè)構(gòu)造函數(shù),所以我們在初始化的時(shí)候可以傳入默認(rèn)數(shù)據(jù)的,只不過我們需要注意傳入默認(rèn)數(shù)據(jù)的格式,它默認(rèn)接收一個(gè)二維數(shù)組。
let defaultMap = new Map([['name', '張三'], ['age', 20]]);
打印出來看看結(jié)果:
插入數(shù)據(jù):
myMap.set('name', '小豬課堂'); // 字符串作為鍵 myMap.set(12, '會飛的豬'); // number 類型作為鍵 myMap.set({}, '知乎'); // 對象類型作為鍵
我們先打印出來看看結(jié)果:
獲取長度:
我們傳統(tǒng)的對象可以通過 Object.key().length
來獲取對象長度,而 map
對象自帶 size
屬性獲取對象長度。
let myMapSize = myMap.size;
獲取值:
let objKey = {}; myMap.set('name', '小豬課堂'); // 字符串作為鍵 myMap.set(12, '會飛的豬'); // number 類型作為鍵 myMap.set(objKey, '知乎'); // 對象類型作為鍵 let name = myMap.get('name'); let age = myMap.get(12); let any = myMap.get(objKey); console.log(name, age, any); // 小豬課堂 會飛的豬 知乎
上段代碼中需要注意的是不能使用 myMap.get({})
的形式獲取數(shù)據(jù),因?yàn)?objKey!=={}
。
刪除某個(gè)值:
myMap.delete('name');
判斷某個(gè)值是否存在:
myMap.has('name'); // 返回 bool 值
2.2 Set 基本使用
Set
對象的使用方式和Map
對象的使用方式非常的類似,只不過存儲的數(shù)據(jù)格式不一樣罷了。這里需要注意的Set
對象存儲的不是鍵值對形式,它只存儲了值,沒有鍵,就和數(shù)組類似。
初始化Set對象:
let mySet = new Set();
初始化Set對象帶有默認(rèn)值:
和Map
類似,Set
初始化時(shí)也可以初始化默認(rèn)數(shù)據(jù)。
let defaultSet = new Set(['張三', 12, true]);
一起來看看輸出結(jié)果:
插入數(shù)據(jù):
mySet.add(1); mySet.add('小豬課堂');
打印結(jié)果:
獲取長度:
let mySetSize = mySet.size;
獲取值:
由于Set
對象存儲的不是鍵值對形式,所以未提供get
方法獲取值,我們通常遍歷它獲取值:
mySet.forEach((item) => { console.log(item) })
刪除某個(gè)值:
mySet.delete(1);
判斷某個(gè)值是否存在:
mySet.has(1); // 返回Boolean值
3.Map和Set區(qū)別
如果我們學(xué)會了它們兩者如何使用,或多或少都知道它們的區(qū)別在哪里,我們這里為大家總結(jié)一下它們的區(qū)別要點(diǎn):
Map
和Set
查找速度都非??欤瑫r(shí)間復(fù)雜度為O(1)
,而數(shù)組查找的時(shí)間復(fù)雜度為O(n)
。Map
對象初始化的值為一個(gè)二維數(shù)組,Set
對象初始化的值為一維數(shù)組。Map
對象和Set對象都不允許鍵重復(fù)(可以將Set
對象的鍵想象成值)。Map
對象的鍵是不能改的,但是值能改,Set
對象只能通過迭代器來更改值。
4.使用場景介紹
4.1 Set對象使用場景
數(shù)組去重
這是大家很熟悉的一種場景,使用Set
對象的唯一性值特性方便的給我們數(shù)組去重。
代碼如下:
let arr = [1, 2, 3, 4, 5, 6, 3, 2, 5, 3, 2]; console.log([...new Set(arr)]); // [1, 2, 3, 4, 5, 6]
需要注意的是Set
對象是一個(gè)類數(shù)組,我們使用...
擴(kuò)展運(yùn)算符將一個(gè)類數(shù)組轉(zhuǎn)化為了一個(gè)真正的數(shù)組。
4.2 Map對象使用場景
數(shù)字類型充當(dāng)鍵
代碼如下:
let errors = new Map([ [400, 'InvalidParameter'], [404, 'Not found'], [500, 'InternalError'] ]); console.log(errors);
輸出結(jié)果:
我們可以使用Map
對象建立一個(gè)請求狀態(tài)碼對象字典,因?yàn)闋顟B(tài)碼是數(shù)字類型,所以使用Map
對象很合適。
除了該場景外,如果需要保證對象的順序,那么也是可以使用Map
對象的。
5.思考點(diǎn)
前面我們說Set
和Map
的插入刪除效率為什么很高呢?
這里簡單講一下,更加深入需要大家自己下去好好學(xué)習(xí)一下數(shù)據(jù)結(jié)構(gòu)了。
簡述原因:
map
和set
存儲的所有元素都是以節(jié)點(diǎn)的方式來進(jìn)行存儲的,這種節(jié)點(diǎn)結(jié)構(gòu)和鏈表有點(diǎn)類似。我們都知道鏈表的特點(diǎn)是插入和刪除都非??欤瑫r(shí)間復(fù)雜度為O(1)
,兩個(gè)節(jié)點(diǎn)通過指針相連,刪除或者增加元素時(shí),我們只是重新更改了指針的指向,不想數(shù)組那樣,摻入或刪除之后需要重新排序。
總結(jié)
Set
對象和Map
對象有很多優(yōu)點(diǎn)的,比如說性能比較好等等,我們需要一一去體會它們的優(yōu)缺點(diǎn)。你不如在每次創(chuàng)建數(shù)據(jù)結(jié)構(gòu)之前想一想:使用Object
更好還是Map
更好呢?使用Array
更好還是Set
更好呢? 當(dāng)然,如果深究Set
和Map
底層原理之后,你會發(fā)現(xiàn)它們的實(shí)現(xiàn)原理就是紅黑樹。
到此這篇關(guān)于一文搞懂Map與Set的用法和區(qū)別的文章就介紹到這了,更多相關(guān)Map與Set用法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
完美解決手機(jī)網(wǎng)頁中輸入框被輸入法遮擋的問題
下面小編就為大家分享一篇完美解決手機(jī)網(wǎng)頁中輸入框被輸入法遮擋的問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2017-12-12js實(shí)現(xiàn)點(diǎn)擊按鈕彈出上傳文件的窗口
本文主要介紹了js實(shí)現(xiàn)點(diǎn)擊按鈕彈出上傳文件的窗口的實(shí)例方法。具有很好的參考價(jià)值,需要的朋友一起來看下吧2016-12-12JS使用Promise時(shí)常見的5個(gè)錯(cuò)誤總結(jié)
Promise?提供了一種優(yōu)雅的方法來處理?JS?中的異步操作。這也是避免“回調(diào)地獄”的解決方案。然而,并沒有多少開發(fā)人員了解其中的內(nèi)容。因此,許多人在實(shí)踐中往往會犯錯(cuò)誤。在本文中,介紹一下使用?promise?時(shí)的五個(gè)常見錯(cuò)誤,希望大家能夠避免2022-11-11js實(shí)現(xiàn)window.open不被攔截的解決方法匯總
這篇文章主要介紹了js實(shí)現(xiàn)window.open不被攔截的解決方法,實(shí)例匯總了常用的不被攔截的解決方法,需要的朋友可以參考下2014-10-10一些Javascript的IE和Firefox(火狐)兼容性的問題總結(jié)及常用例子
下面是一些Javascript的IE和Firefox(火狐)兼容性的常用例子2009-05-05微信小程序自定義菜單切換欄tabbar組件代碼實(shí)例
這篇文章主要介紹了微信小程序自定義菜單切換欄tabbar組件代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12