數(shù)據(jù)結(jié)構(gòu)一向是找工作時(shí)的考點(diǎn)及難點(diǎn),在此我們簡(jiǎn)單以實(shí)例來簡(jiǎn)單對(duì)HashMap及LinkHashMap進(jìn)行說明。
# 前言(fei hua)
其實(shí)所有的數(shù)據(jù)結(jié)構(gòu)最終都是在解決**取數(shù)**的問題,而如何能夠按照要求要**取數(shù)**,則需要有一個(gè)良好的**存數(shù)**機(jī)制,現(xiàn)實(shí)生活中最典型的數(shù)據(jù)結(jié)構(gòu)就是我們身邊的圖書館了,圖書館那規(guī)則對(duì)圖書進(jìn)行編碼,比如我們查詢某本圖書得到以下信息:

我們按此提示信息,來到紅橋管閱覽二區(qū)找到**分類號(hào)**TP314.12對(duì)應(yīng)的圖書區(qū),然后在按該索引號(hào)的**字順**逐漸的找到我們想借閱的書籍。只所以能夠按上述的規(guī)則找到相關(guān)的書籍,是由于在進(jìn)行圖書上架時(shí)先對(duì)圖片進(jìn)行了分類、編碼,然后按分類編碼進(jìn)行了相應(yīng)的存放。這其實(shí)就是一種數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu)規(guī)定了如果存數(shù)據(jù),同時(shí)又按存數(shù)據(jù)的規(guī)則來規(guī)定了如何取數(shù)據(jù)。
回想一下第一次去圖書館的經(jīng)歷是非常痛苦的,雖然可以根據(jù)索引號(hào)來快速的獲取分類號(hào),但TP31X的圖書真是太多了。按**字順**索引的方式,很難由TP311(程序設(shè)計(jì)、軟件工程)、TP312(程序語言、算法語言)等熱門的書籍中快速找到我們想到的那本。
# HashMap
HashMap的出現(xiàn),便很好的解決當(dāng)前了問題。關(guān)于HashMap的文章google一搜一大把,具體的原理層面的就是不在這里重復(fù)講了。在此,我們舉個(gè)小例子來幫助大家來理解這個(gè)HashMap。
## 情景模擬
我們假設(shè)以下情景:
* [ ] 你有90張銀行卡片,這些銀行卡片的尾號(hào)是隨機(jī)的
* [ ] 你有很多張小卡片,每張小卡片僅可記錄1個(gè)兩位數(shù)
* [ ] 你家中有100個(gè)可以存放銀行卡片的儲(chǔ)物格,每個(gè)儲(chǔ)物格均存放了一張銀行卡片和一張小卡片
* [ ] 對(duì)100個(gè)儲(chǔ)物格進(jìn)行編號(hào),范圍為0-99。
## 問題
你每天都需要隨機(jī)的由支付定綁定的銀行卡列表中找一張銀行卡,進(jìn)而去ATM機(jī)提現(xiàn),那你如何能夠快速的由儲(chǔ)物格中找到這張卡片。
## 解決方案
HashMap是解決方案的一種,它的解決方案大體如下:
首先,拿出10個(gè)小卡片順序排列(0-9號(hào)),并將每個(gè)儲(chǔ)物格內(nèi)內(nèi)置一張小卡片:

然后假設(shè)依次裝入100張銀行卡,前10張卡的卡號(hào)分別為:
```
xxxxxxxxx1025
xxxxxxxxx7842
xxxxxxxxx9863
xxxxxxxxx5625
xxxxxxxxx2324
xxxxxxxxx6532
xxxxxxxxx3699
xxxxxxxxx9845
xxxxxxxxx6242
```
### 存數(shù)據(jù)
第銀行卡102`5`裝入`0`號(hào)儲(chǔ)物格,同時(shí)將第`5`號(hào)小卡片的值設(shè)置為`0`

將銀行卡784`2`裝入`1`號(hào)儲(chǔ)物格,同時(shí)將第`2`號(hào)小卡片的值設(shè)置為`1`;將銀行卡986`3`裝入第`2`號(hào)儲(chǔ)物格,同時(shí)將第`3`號(hào)小卡片的值設(shè)置為`2`。

將銀行卡562`5`裝入第`3`號(hào)儲(chǔ)物格。同時(shí)嘗試將第`5`號(hào)小卡片的值設(shè)置為`3`:
* [ ] 1. 如果該小卡片空白,則寫入`3`,程序終止
* [ ] 2. 否則獲取小卡片上的值
* [ ] 3. 找到該值對(duì)應(yīng)的儲(chǔ)物格中的小卡片
* [ ] 4. 重復(fù)1
所以我們獲取到了5號(hào)小卡片上的值0,來到了0號(hào)儲(chǔ)物格并取出其小卡片,并寫入3.

繼續(xù)按上述規(guī)則存入2324、6532兩張銀行卡:

仔細(xì)的觀察上圖,我們好像發(fā)現(xiàn)了一個(gè)規(guī)律,那就是小卡片上記錄的文字即是儲(chǔ)物格的編號(hào)。如果將小卡片與儲(chǔ)物格用顏色進(jìn)行關(guān)聯(lián),則將得到下圖:

我們剛剛順序的存放了幾張銀行卡,其實(shí)這并不是必須的,比如我們可以將下一張3699尾號(hào)的銀行卡直接放到7號(hào)儲(chǔ)物格中:

這完全沒有任何問題,我們繼續(xù)按上面的規(guī)則將9845放到第10號(hào)儲(chǔ)物格(假設(shè)第8,9號(hào)儲(chǔ)物格暫不可用)中:

其尾號(hào)為5,則找第5號(hào)卡片,得到值0 -> 繼續(xù)找第0號(hào)儲(chǔ)物格,得到0號(hào)儲(chǔ)物格的小卡片的值3 -> 繼續(xù)找第3號(hào)儲(chǔ)物格, 得到該儲(chǔ)物格中的空白小卡片,于是將10寫入到該卡片上。

> 最后一張銀行卡,你來放吧。
### 取數(shù)據(jù)
數(shù)據(jù)存好了,取就簡(jiǎn)單了。假設(shè)我們要取7842的銀行卡。
* 9842的尾號(hào)為2
* 找到第2號(hào)小卡片,獲取值1
* 找到1號(hào)儲(chǔ)物格,該銀行卡即為我們想要的9842
假設(shè)我們要找9845號(hào)銀行卡:
* 9845的尾號(hào)為5
* 找到第5號(hào)小卡,獲取值0
* 找到第0號(hào)儲(chǔ)物格,獲取銀行卡1025,不是我們要找的9845,則讀取該儲(chǔ)物盒中的小卡片的值3
* 找到第3號(hào)儲(chǔ)物格,獲取銀行卡5825,不是我們要找的9845,則讀取該儲(chǔ)物盒中的小卡片的值10
* 找到第10號(hào)儲(chǔ)物格,獲取銀行卡9845,返回。
假設(shè)我們要找9999號(hào)銀行卡
* 9999的尾號(hào)為9
* 找到第9號(hào)小卡,獲取值7
* 找到第7號(hào)儲(chǔ)物格,獲取銀行卡3699,不是我們要找的9999,則讀取該儲(chǔ)物盒中的小卡片的值
* 該卡片無值,表明我們未存儲(chǔ)尾號(hào)為9999的銀行卡,返回null
以上存銀行卡的過程,即是HaspMap的存值和取值過程,刪除數(shù)據(jù)的過程也不復(fù)雜,主要是要考慮刪除數(shù)據(jù)不能對(duì)歷史的數(shù)據(jù)查詢?cè)斐捎绊?。比如我們想刪除1025這個(gè)銀行卡,則:
* [ ] 通過小卡片A找到該銀行卡所在的儲(chǔ)物格
* [ ] 獲取該儲(chǔ)物格的小卡片B
* [ ] 將小卡片B移到小卡片A的位置
* [ ] 清空該儲(chǔ)物格(移除銀行卡、放置新的小卡片)

將小卡片B(數(shù)值為3)移到小卡片A(數(shù)值為0)的位置,清空0號(hào)儲(chǔ)物格中后:

# 圖的認(rèn)讀
在計(jì)算機(jī)中,無論是小卡片還是儲(chǔ)物格,對(duì)應(yīng)的都是**內(nèi)存**,內(nèi)存是連續(xù)的存儲(chǔ)空間,就像我們剛剛看到的連續(xù)的儲(chǔ)物格。我們常說計(jì)算機(jī)是**內(nèi)存**最小的單元是位bit,每位可以存儲(chǔ)一個(gè)二進(jìn)制0或1。對(duì)內(nèi)存操作時(shí),往往會(huì)把8位看做一個(gè)整體來進(jìn)行集中操作,這是由于`位`的粒度實(shí)在是太小了,就像現(xiàn)實(shí)生活中我們無法購買一粒瓜子以及無法購法1ml的牛奶是一個(gè)道理。在計(jì)算機(jī)中,把8個(gè)位組成的連續(xù)存儲(chǔ)單元稱為1個(gè)字節(jié),這便是內(nèi)存單元的最小粒度,也是我們?cè)趯W(xué)習(xí)相關(guān)的理論課時(shí)1Byte = 8bit的根本原因。前面我們學(xué)習(xí)過了字符的編碼,經(jīng)查詢?cè)赨TF-8編碼中`夢(mèng)`的編碼為:`0xE6 0xA2 0xA6 (e6a2a6)`;也學(xué)習(xí)過ascii編碼,經(jīng)查詢`i`的編碼為`0x69`。則在內(nèi)存中是如下存儲(chǔ)`i夢(mèng)`這兩個(gè)字符的:

由于4個(gè)二進(jìn)制(位)恰好可以用1個(gè)16進(jìn)制來表示,所以為了易于交流、閱讀,我們通常會(huì)將二進(jìn)制轉(zhuǎn)換為16進(jìn)制。進(jìn)而在一個(gè)內(nèi)存單元中,便由8個(gè)二制進(jìn)的位變?yōu)?個(gè)16進(jìn)制的字符了。比如我們?cè)谑謾C(jī)中查看硬件信息(ios中請(qǐng)依次點(diǎn)擊:通用 -> 關(guān)于本機(jī)),會(huì)發(fā)現(xiàn)無線局域網(wǎng)地址、藍(lán)牙設(shè)置的信息。該信息即是用16進(jìn)制來表示的二進(jìn)制,比如我的手機(jī)無線局域網(wǎng)地址為:`80:82:D5:...`,每?jī)晌?6進(jìn)制為1組,這2個(gè)16進(jìn)制共同表示了一個(gè)字節(jié)的內(nèi)容;在比如我們進(jìn)行IP地址設(shè)置時(shí),假設(shè)設(shè)定值為:`192.168.0.1`,中間之所以用`.`進(jìn)行分離,也是由于每個(gè)分隔的數(shù)字代表了一個(gè)字節(jié),8個(gè)二進(jìn)制(1個(gè)字節(jié))在無符號(hào)數(shù)中的取值范圍是0-255,所以當(dāng)我們?cè)O(shè)置IP地址的相關(guān)參數(shù)時(shí),最大值不會(huì)超出255,也就是16進(jìn)制的FF,如果超出這個(gè)值,1個(gè)字節(jié)就放不下了,所以當(dāng)我們嘗試使用大于255的值設(shè)置IP地址的相關(guān)值時(shí),操作系統(tǒng)會(huì)使用自己的錯(cuò)誤提醒機(jī)制來提醒我們。
我們?cè)谟?jì)算機(jī)專業(yè)課的學(xué)習(xí)過程中,常常會(huì)看到這樣表示內(nèi)存:

每個(gè)內(nèi)存單元均表示8個(gè)二進(jìn)制數(shù),即一個(gè)字節(jié)。在表示過程中,常用兩個(gè)16進(jìn)制數(shù)來表示:

內(nèi)存是連續(xù)的存儲(chǔ)空間,但由于印刷方便的原因,在進(jìn)行一些內(nèi)存展示的時(shí)候,我們無法在一行中將所有的內(nèi)存單元一字排開。所以才采用了上面的展示方法,也就是說每行的最后一個(gè)內(nèi)存單元與下一行的第一個(gè)內(nèi)存單元實(shí)際上是鄰居:

左側(cè)與上側(cè)的數(shù)字共同決定了某塊內(nèi)存單元的編號(hào),此編號(hào)的最小值為0,最大為FFFFH(16位機(jī))或FFFF FFFFH (32位機(jī))或FFFF FFFF FFFF FFFFH(64位機(jī))。在各種演示及圖表中,我們更喜歡使用位數(shù)更少的16位機(jī)地址來做示例,16位機(jī)較32、64位機(jī)而言除了長(zhǎng)度不同以外,其它的均相同。隨便找3個(gè)內(nèi)存單元,他們地址如下:

有部分圖解中,也會(huì)用豎直的方式來表示內(nèi)存:

這與橫向使用完全相同,只所以豎著用也是完全出于印刷的角度。如果使用此段內(nèi)存的4-7號(hào)來存儲(chǔ)`i夢(mèng)`,則在數(shù)據(jù)結(jié)構(gòu)中相應(yīng)圖表中,會(huì)如下表示:

## 計(jì)算機(jī)中的HASHMAP
有了前面看圖表的基礎(chǔ)知識(shí),結(jié)合google再理解hashMap就不難了,由網(wǎng)上找到了一張?jiān)瓐D如下:

加入圖解后:

計(jì)算機(jī)的HashMap存數(shù)據(jù)與我們的在存儲(chǔ)格中存銀行卡大同小異,它大概經(jīng)歷這么4個(gè)步驟。
* [ ] 拿出16個(gè)小卡片(連續(xù)的內(nèi)存單元)
* [ ] 隨便找塊連續(xù)內(nèi)存,存對(duì)象(實(shí)際上為對(duì)象的引用)以及next小卡片,并記錄該連續(xù)內(nèi)存的**起始地址**。
* [ ] 獲取存入對(duì)象的hash值(JVM提供,基于內(nèi)存地址),比如獲取到的值為2657860
* [ ] 使用對(duì)象的hash值與(16 - 1)相與,得到一個(gè)0 - 15之間的值,比如 `2657860?&?(16-1)?=?4`,結(jié)果為4
* [ ] 去4號(hào)卡片找值,該卡片如果無值,則將**起始地址**存入;如果有值,則按該值去找連續(xù)內(nèi)存單元中的next;next無值,便存入**起始地址**,有值則繼續(xù)向下找。
我們以16位機(jī)為例,在上圖的基礎(chǔ)上存入`i夢(mèng)`、`i云`、`i智`:

則表示實(shí)際在內(nèi)存中如下進(jìn)行存儲(chǔ):

它們間的對(duì)應(yīng)關(guān)系為:

# LinkedHashMap
LInkedHashMap結(jié)合了HashMap及雙向鏈表,它犧牲了部分查詢效率,多占用了一些內(nèi)存空間,但解決了HashMap無序的特點(diǎn)。
> 在獲取HaspMap中的全部數(shù)據(jù)時(shí),它輸出數(shù)據(jù)的順序并不取決于輸入數(shù)據(jù)的順序。也就是說,同是一組數(shù)據(jù)輸入HashMap,無論你的輸入順序是什么,最終循環(huán)獲取HashMap中的值時(shí),得到的輸出順序都是一致的。
## 基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)

在儲(chǔ)物格中又增加了一張卡片來記錄上一條數(shù)據(jù)的位置。
* before 上一條數(shù)據(jù)的位置(連續(xù)內(nèi)存存儲(chǔ)起始位置)
* key、value兩個(gè)數(shù)據(jù)項(xiàng)
* after 下一條數(shù)據(jù)的位置
## 第一次添加數(shù)據(jù)
`put(cbr250r, null)`,計(jì)算cbr250的hash值與15相與的值為10

* 與HashMap相同,LinkHashMap先創(chuàng)建了大小為16的連續(xù)內(nèi)存空間,并添加數(shù)據(jù)
* 增加了兩個(gè)屬性head與tail分別記錄頭與尾,并將這兩個(gè)屬性同時(shí)指向了該數(shù)據(jù)。
> 其實(shí)16這個(gè)數(shù)字并不準(zhǔn)確,相對(duì)于8位機(jī),它的大小就是16;但相對(duì)于16位機(jī),我們則需要2個(gè)字節(jié)( 2 * 8 = 16 ) 來存儲(chǔ)內(nèi)存地址,所以它的大小應(yīng)該是`16 * 2 = 32`,然后每2個(gè)連續(xù)的內(nèi)存單元來共同存儲(chǔ)一個(gè)內(nèi)存地址;32位機(jī)則需要4個(gè)字節(jié),64位機(jī)則需要8個(gè)字節(jié)。
## 第二次添加數(shù)據(jù)
`put(cbr1000rr, null);` ,計(jì)算cbr1000rr的hash值與15相與的值為8

* head不變,tail指向了新的數(shù)據(jù)。同時(shí)更新原數(shù)據(jù)的after及新數(shù)據(jù)的before,達(dá)到首尾互聯(lián)的目的。
## 第三次添加數(shù)據(jù)
`put(ninja250r, null);`,計(jì)算ninja250r的hash值與15相與的值為10

* 原10號(hào)小卡片有值,則找tail指向的數(shù)據(jù),并將新數(shù)據(jù)的起始內(nèi)存位置加入到該數(shù)據(jù)的next上。
## 第四次添加數(shù)據(jù)
`put(ninja1000rr, null);`,計(jì)算ninja1000rr的hash值與15相與的值為8

* 原8號(hào)小卡片有值,則找tail指向的數(shù)據(jù),并將新數(shù)據(jù)的起始內(nèi)存位置加入到該數(shù)據(jù)的next上。
此時(shí),當(dāng)我們需要對(duì)LinkedHashMap中的值進(jìn)行便歷時(shí),便可以由head入手,一直查到tail了,而且輸入的順序與輸入的順序保持了一致。
# 其它
以上理論均基于以下現(xiàn)實(shí):
* 計(jì)算機(jī)具有非凡的計(jì)算能力,特別是進(jìn)行位操作,比如`與`運(yùn)算
* 計(jì)算機(jī)具有直接尋址的能力,只要你告訴它內(nèi)存的編號(hào),它便可以直接定位到該內(nèi)存
# 參考文檔
| 名稱 | 鏈接 | 預(yù)計(jì)學(xué)習(xí)時(shí)長(zhǎng)(分) |
| --- | --- | --- |
| Working of LinkedHashMap | [http://www.thejavageek.com/2016/06/05/working-linkedhashmap-java/](http://www.thejavageek.com/2016/06/05/working-linkedhashmap-java/) | - |
- 序言
- 第一章:Hello World
- 第一節(jié):Angular準(zhǔn)備工作
- 1 Node.js
- 2 npm
- 3 WebStorm
- 第二節(jié):Hello Angular
- 第三節(jié):Spring Boot準(zhǔn)備工作
- 1 JDK
- 2 MAVEN
- 3 IDEA
- 第四節(jié):Hello Spring Boot
- 1 Spring Initializr
- 2 Hello Spring Boot!
- 3 maven國內(nèi)源配置
- 4 package與import
- 第五節(jié):Hello Spring Boot + Angular
- 1 依賴注入【前】
- 2 HttpClient獲取數(shù)據(jù)【前】
- 3 數(shù)據(jù)綁定【前】
- 4 回調(diào)函數(shù)【選學(xué)】
- 第二章 教師管理
- 第一節(jié) 數(shù)據(jù)庫初始化
- 第二節(jié) CRUD之R查數(shù)據(jù)
- 1 原型初始化【前】
- 2 連接數(shù)據(jù)庫【后】
- 3 使用JDBC讀取數(shù)據(jù)【后】
- 4 前后臺(tái)對(duì)接
- 5 ng-if【前】
- 6 日期管道【前】
- 第三節(jié) CRUD之C增數(shù)據(jù)
- 1 新建組件并映射路由【前】
- 2 模板驅(qū)動(dòng)表單【前】
- 3 httpClient post請(qǐng)求【前】
- 4 保存數(shù)據(jù)【后】
- 5 組件間調(diào)用【前】
- 第四節(jié) CRUD之U改數(shù)據(jù)
- 1 路由參數(shù)【前】
- 2 請(qǐng)求映射【后】
- 3 前后臺(tái)對(duì)接【前】
- 4 更新數(shù)據(jù)【前】
- 5 更新某個(gè)教師【后】
- 6 路由器鏈接【前】
- 7 觀察者模式【前】
- 第五節(jié) CRUD之D刪數(shù)據(jù)
- 1 綁定到用戶輸入事件【前】
- 2 刪除某個(gè)教師【后】
- 第六節(jié) 代碼重構(gòu)
- 1 文件夾化【前】
- 2 優(yōu)化交互體驗(yàn)【前】
- 3 相對(duì)與絕對(duì)地址【前】
- 第三章 班級(jí)管理
- 第一節(jié) JPA初始化數(shù)據(jù)表
- 第二節(jié) 班級(jí)列表
- 1 新建模塊【前】
- 2 初識(shí)單元測(cè)試【前】
- 3 初始化原型【前】
- 4 面向?qū)ο蟆厩啊?/a>
- 5 測(cè)試HTTP請(qǐng)求【前】
- 6 測(cè)試INPUT【前】
- 7 測(cè)試BUTTON【前】
- 8 @RequestParam【后】
- 9 Repository【后】
- 10 前后臺(tái)對(duì)接【前】
- 第三節(jié) 新增班級(jí)
- 1 初始化【前】
- 2 響應(yīng)式表單【前】
- 3 測(cè)試POST請(qǐng)求【前】
- 4 JPA插入數(shù)據(jù)【后】
- 5 單元測(cè)試【后】
- 6 惰性加載【前】
- 7 對(duì)接【前】
- 第四節(jié) 編輯班級(jí)
- 1 FormGroup【前】
- 2 x、[x]、{{x}}與(x)【前】
- 3 模擬路由服務(wù)【前】
- 4 測(cè)試間諜spy【前】
- 5 使用JPA更新數(shù)據(jù)【后】
- 6 分層開發(fā)【后】
- 7 前后臺(tái)對(duì)接
- 8 深入imports【前】
- 9 深入exports【前】
- 第五節(jié) 選擇教師組件
- 1 初始化【前】
- 2 動(dòng)態(tài)數(shù)據(jù)綁定【前】
- 3 初識(shí)泛型
- 4 @Output()【前】
- 5 @Input()【前】
- 6 再識(shí)單元測(cè)試【前】
- 7 其它問題
- 第六節(jié) 刪除班級(jí)
- 1 TDD【前】
- 2 TDD【后】
- 3 前后臺(tái)對(duì)接
- 第四章 學(xué)生管理
- 第一節(jié) 引入Bootstrap【前】
- 第二節(jié) NAV導(dǎo)航組件【前】
- 1 初始化
- 2 Bootstrap格式化
- 3 RouterLinkActive
- 第三節(jié) footer組件【前】
- 第四節(jié) 歡迎界面【前】
- 第五節(jié) 新增學(xué)生
- 1 初始化【前】
- 2 選擇班級(jí)組件【前】
- 3 復(fù)用選擇組件【前】
- 4 完善功能【前】
- 5 MVC【前】
- 6 非NULL校驗(yàn)【后】
- 7 唯一性校驗(yàn)【后】
- 8 @PrePersist【后】
- 9 CM層開發(fā)【后】
- 10 集成測(cè)試
- 第六節(jié) 學(xué)生列表
- 1 分頁【后】
- 2 HashMap與LinkedHashMap
- 3 初識(shí)綜合查詢【后】
- 4 綜合查詢進(jìn)階【后】
- 5 小試綜合查詢【后】
- 6 初始化【前】
- 7 M層【前】
- 8 單元測(cè)試與分頁【前】
- 9 單選與多選【前】
- 10 集成測(cè)試
- 第七節(jié) 編輯學(xué)生
- 1 初始化【前】
- 2 嵌套組件測(cè)試【前】
- 3 功能開發(fā)【前】
- 4 JsonPath【后】
- 5 spyOn【后】
- 6 集成測(cè)試
- 7 @Input 異步傳值【前】
- 8 值傳遞與引入傳遞
- 9 @PreUpdate【后】
- 10 表單驗(yàn)證【前】
- 第八節(jié) 刪除學(xué)生
- 1 CSS選擇器【前】
- 2 confirm【前】
- 3 功能開發(fā)與測(cè)試【后】
- 4 集成測(cè)試
- 5 定制提示框【前】
- 6 引入圖標(biāo)庫【前】
- 第九節(jié) 集成測(cè)試
- 第五章 登錄與注銷
- 第一節(jié):普通登錄
- 1 原型【前】
- 2 功能設(shè)計(jì)【前】
- 3 功能設(shè)計(jì)【后】
- 4 應(yīng)用登錄組件【前】
- 5 注銷【前】
- 6 保留登錄狀態(tài)【前】
- 第二節(jié):你是誰
- 1 過濾器【后】
- 2 令牌機(jī)制【后】
- 3 裝飾器模式【后】
- 4 攔截器【前】
- 5 RxJS操作符【前】
- 6 用戶登錄與注銷【后】
- 7 個(gè)人中心【前】
- 8 攔截器【后】
- 9 集成測(cè)試
- 10 單例模式
- 第六章 課程管理
- 第一節(jié) 新增課程
- 1 初始化【前】
- 2 嵌套組件測(cè)試【前】
- 3 async管道【前】
- 4 優(yōu)雅的測(cè)試【前】
- 5 功能開發(fā)【前】
- 6 實(shí)體監(jiān)聽器【后】
- 7 @ManyToMany【后】
- 8 集成測(cè)試【前】
- 9 異步驗(yàn)證器【前】
- 10 詳解CORS【前】
- 第二節(jié) 課程列表
- 第三節(jié) 果斷
- 1 初始化【前】
- 2 分頁組件【前】
- 2 分頁組件【前】
- 3 綜合查詢【前】
- 4 綜合查詢【后】
- 4 綜合查詢【后】
- 第節(jié) 班級(jí)列表
- 第節(jié) 教師列表
- 第節(jié) 編輯課程
- TODO返回機(jī)制【前】
- 4 彈出框組件【前】
- 5 多路由出口【前】
- 第節(jié) 刪除課程
- 第七章 權(quán)限管理
- 第一節(jié) AOP
- 總結(jié)
- 開發(fā)規(guī)范
- 備用