版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
JavaLinkedHashMapLRU為O(1)。現(xiàn)在,我們就來(lái)看看它是如何做到的。首先,我們來(lái)回顧一下當(dāng)時(shí)我們是如何通過(guò)鏈表實(shí)現(xiàn)LRU緩存淘汰算法的。當(dāng)要緩存某個(gè)數(shù)據(jù)的時(shí)候,先在鏈表中查找這個(gè)數(shù)據(jù)。如果沒(méi)有找到,則直接將數(shù)據(jù)放到鏈表的尾部;如果找到了,我們就把它移動(dòng)到鏈表的尾部。因?yàn)椴檎覕?shù)據(jù)需要遍歷鏈表,所以單純用鏈表實(shí)現(xiàn)的LRU緩存淘汰算法的時(shí)間復(fù)雜很高,是O()。這三個(gè)操作都要涉及“查找”操作,如果單純地采用鏈表的話,時(shí)間復(fù)雜度只能是O(n)。(prev)、后繼指針(next)hnexthnext因?yàn)槲覀兊纳⒘斜硎峭ㄟ^(guò)鏈表法解決散列的,所以每個(gè)結(jié)點(diǎn)會(huì)在兩條鏈中。一個(gè)鏈?zhǔn)莿倓偽覀兲岬降碾p向鏈表,另一個(gè)鏈?zhǔn)巧⒘斜碇械睦湣G膀?qū)和后繼指針是為了將結(jié)點(diǎn)串在雙向鏈表中,hnext指針是為了將結(jié)點(diǎn)串在散列表的拉鏈中。了解了這個(gè)散列表和雙向鏈表的組合結(jié)構(gòu)之后,我們?cè)賮?lái)看,前面講到的緩存的三個(gè)操作,是如何做到時(shí)間復(fù)雜度是O(1)的?首先,我們來(lái)看如何查找一個(gè)數(shù)據(jù)。我們前面講過(guò),散列表中查找數(shù)據(jù)的時(shí)間復(fù)雜度接近O1),所以通過(guò)散列表,我們可以很快地在緩存中找到一個(gè)數(shù)據(jù)。當(dāng)找到數(shù)據(jù)之后,我們還需要將它移動(dòng)到雙向鏈表的尾部。其次,我們來(lái)看如何刪除一個(gè)數(shù)據(jù)。我們需要找到數(shù)據(jù)所在的結(jié)點(diǎn),然后將結(jié)點(diǎn)刪除。借助散列表,我們可以在O(1)時(shí)間復(fù)雜度里找到要?jiǎng)h除的結(jié)點(diǎn)。因?yàn)槲覀兊逆湵硎请p向鏈表,雙向鏈表可以通過(guò)前驅(qū)指針O(1)時(shí)間復(fù)雜度獲取前驅(qū)結(jié)點(diǎn),所以在雙向鏈表中,刪除結(jié)點(diǎn)只需要O(1)的時(shí)間復(fù)雜度。最后,我們來(lái)看如何添加一個(gè)數(shù)據(jù)。添加數(shù)據(jù)到緩存稍微有點(diǎn)麻煩,我們需要先看這個(gè)數(shù)據(jù)是否已經(jīng)在緩存中。如果已經(jīng)在其中,需要將其移動(dòng)到雙向鏈表的尾部;如果不在其中,還要看緩存有沒(méi)有滿。如果滿了,則將雙向鏈表頭部的結(jié)點(diǎn)刪除,然后再將數(shù)據(jù)放到鏈表的尾部;如果沒(méi)有滿,就直接將數(shù)據(jù)放到鏈表的尾部。這整個(gè)過(guò)程涉及的查找操作都可以通過(guò)散列表來(lái)完成。其他的操作,比如刪除頭結(jié)點(diǎn)、鏈表尾部插入數(shù)據(jù)等,都可以在O1)的時(shí)間復(fù)雜度內(nèi)完成。所以,這三個(gè)操作的時(shí)間復(fù)雜度都是O(1)。至此,我們就通過(guò)散列表和雙向鏈表的組合使用,實(shí)現(xiàn)了一個(gè)高效的、支持LRU緩存淘汰算法的緩存系統(tǒng)原型。Redis在跳表那一節(jié),講到有序集合的操作時(shí),我稍微做了些簡(jiǎn)化。實(shí)際上,在有序集合中,每個(gè)成員對(duì)象有兩個(gè)重要的屬性,key(鍵值)和scre(分值)。我們不僅會(huì)通過(guò)score來(lái)查找數(shù)據(jù),還會(huì)通過(guò)ey來(lái)查找數(shù)據(jù)。舉個(gè)例子,比如用戶積分榜有這樣一個(gè)功能:我們可以通過(guò)用戶的ID來(lái)查找積分息,也可以通過(guò)積分區(qū)間來(lái)查找用戶ID或者信息。這里包含ID、和積分的用戶信息,就是成員對(duì)象,用戶ID就是key,積分就是score。所以,如果我們細(xì)化一下Redis有序集合的操作,那就是下面這樣:100356會(huì)很慢,解決方法與LRU緩存淘汰算法的解決方法類似。我們可以再按照鍵值構(gòu)建一個(gè)散列表,這樣按照key來(lái)刪除、查找一個(gè)成員對(duì)象的時(shí)間復(fù)雜度就變成了O(1)。同時(shí),借助實(shí)際上,Reis有序集合的操作還有另外一類,也就是查找成員對(duì)象的(Rank)或者根據(jù)區(qū)間查找成員對(duì)象。這個(gè)功能單純用剛剛講的這種組合結(jié)構(gòu)就無(wú)法高效實(shí)現(xiàn)了。這塊內(nèi)容我后面的章節(jié)再講。JavaJava,那你幾乎天天會(huì)用到這個(gè)容器。我們之前講過(guò),HashMap散列表這種數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)的。而LinkedHashMap前面比HashMap多了一個(gè)“Linked”,這里的“Linked”是不是說(shuō),LinkedHashMap實(shí)際上,LinkedHashMapLinked”也并不僅僅代表它是通過(guò)HashMap<Integer,Integer>m=newm.put(3,m.put(1,m.put(5,m.put(2,6for(Map.Entrye:m.entrySet())9是3,1,5,2。你有沒(méi)有覺(jué)得奇怪?散列表中數(shù)據(jù)是經(jīng)過(guò)散列函數(shù)打亂之后無(wú)規(guī)律//10是初始大小,0.75是裝載因子,true是表示按照時(shí)間排HashMap<Integer,Integer>m=newLinkedHashMap<>(10,0.75f,3456789for(Map.Entrye:m.entrySet())13這段代碼打印的結(jié)果是1,2,3,5。我來(lái)具體分析一下,為什么這段代碼會(huì)按照這樣順序每次調(diào)用put()函數(shù),往LinkedHashMap中添加數(shù)據(jù)的時(shí)候,都會(huì)將數(shù)據(jù)添加到鏈表的在第8行代碼中,再次將鍵值為3的數(shù)據(jù)放入到LinkedHashMap的時(shí)候,會(huì)先查找這個(gè)鍵值是否已經(jīng)有了,然后,再將已經(jīng)存在的(3,11)刪除,并且將新的(3,26)放到鏈表的尾當(dāng)?shù)?行代碼到key為5的數(shù)據(jù)的時(shí)候,被到的數(shù)據(jù)移動(dòng)到鏈表的尾部。所以,第9行代碼之后,鏈表中的數(shù)據(jù)是下面這樣:所以,最后打印出來(lái)的數(shù)據(jù)是1,2,3,5。從上面的分析,你有沒(méi)有發(fā)現(xiàn),按照時(shí)間排序的LinkedHashMap本身就是一個(gè)支持LRU緩存淘汰策略的緩存系統(tǒng)?實(shí)際上,它們我現(xiàn)在來(lái)總結(jié)一下,實(shí)際上,LinkedHashMap是通過(guò)雙向鏈表和散列表這兩種數(shù)據(jù)結(jié)構(gòu)組合實(shí)現(xiàn)的。LinkedHashMap中的“Linked”實(shí)際上是指的是雙向鏈表,并非指用鏈表&散列表這種數(shù)據(jù)結(jié)構(gòu)雖然支持非常高效的數(shù)據(jù)插入、刪除、查找操作,但是散列表中的數(shù)據(jù)都是通過(guò)散列函數(shù)打亂之后無(wú)規(guī)律的。也就說(shuō),它無(wú)法支持按照某種順序快速地遍歷數(shù)據(jù)。如果希望按照順序遍歷散列表中的數(shù)據(jù),那我們需要將散列表中的數(shù)據(jù)拷貝到數(shù)組中,然后排序,再遍歷。因?yàn)樯⒘斜硎莿?dòng)態(tài)數(shù)據(jù)結(jié)構(gòu),不停地有數(shù)據(jù)的插入、刪除,所以每當(dāng)我們希望按順序遍歷散列表中的數(shù)據(jù)的時(shí)候,都需要先排序,那效率勢(shì)必會(huì)很低。為了解決這個(gè)問(wèn)題,散列表和鏈表(或者跳表)結(jié)合在一起使用。假設(shè)獵聘網(wǎng)有10萬(wàn)名獵頭,每個(gè)獵頭都可以通過(guò)做任務(wù)(比如發(fā)布職位)來(lái)積累積分,然后通過(guò)積分來(lái)簡(jiǎn)歷。假設(shè)你是獵聘網(wǎng)的一名工程師,如何在內(nèi)存中這10萬(wàn)個(gè)獵頭ID和積分信息,讓它能夠支持這樣幾個(gè)操作:ID查找積分在某個(gè)區(qū)間的獵頭ID列表;查找按照積分從小到大在第x位到第y位之間的獵頭ID列表。?歸科技所有,不得售賣。頁(yè)面已增加防盜追蹤,將依法其上一 19|散列表(中):如何打造一個(gè)工業(yè)級(jí)水平的散列表下一 21|哈希算法(上):如何防止數(shù)據(jù)庫(kù)中的用戶信息被脫庫(kù)
271??
110的指針,遍歷到前一個(gè)結(jié)點(diǎn)復(fù)雜度會(huì)變?yōu)镺(N),所以用雙鏈表實(shí)現(xiàn)比較合適。…作者回復(fù):??其他同學(xué)這條留姜 Zeng 11 莫問(wèn)流 10微 虢 4 小智 4 就是結(jié)合你的圖也看不懂啊
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024硬件設(shè)備代理與售后服務(wù)合作協(xié)議2篇
- 2025年度GPS技術(shù)在應(yīng)急救援領(lǐng)域的應(yīng)用合作協(xié)議3篇
- 二零二四年商務(wù)考察接送服務(wù)合同模板3篇
- 2024食用菌品牌授權(quán)與營(yíng)銷推廣合同3篇
- 2025年校園安保服務(wù)合同含校園安全設(shè)施建設(shè)及維護(hù)協(xié)議3篇
- 2025年消防應(yīng)急照明及疏散指示系統(tǒng)采購(gòu)合同范本2篇
- 二零二五年度海鮮餐廳特許經(jīng)營(yíng)許可合同3篇
- 二零二五版煤礦掘進(jìn)設(shè)備出租及維護(hù)保養(yǎng)服務(wù)合同3篇
- 二零二五版廠房租賃合同終止及費(fèi)用結(jié)算及保險(xiǎn)服務(wù)協(xié)議3篇
- 二零二五年建筑施工人員雇傭合同3篇
- 直播帶貨助農(nóng)現(xiàn)狀及發(fā)展對(duì)策研究-以抖音直播為例(開(kāi)題)
- 腰椎間盤突出疑難病例討論
- 《光伏發(fā)電工程工程量清單計(jì)價(jià)規(guī)范》
- 2023-2024學(xué)年度人教版四年級(jí)語(yǔ)文上冊(cè)寒假作業(yè)
- (完整版)保證藥品信息來(lái)源合法、真實(shí)、安全的管理措施、情況說(shuō)明及相關(guān)證明
- 營(yíng)銷專員績(jī)效考核指標(biāo)
- 陜西麟游風(fēng)電吊裝方案專家論證版
- 供應(yīng)商審核培訓(xùn)教程
- 【盒馬鮮生生鮮類產(chǎn)品配送服務(wù)問(wèn)題及優(yōu)化建議分析10000字(論文)】
- 肝硬化心衰患者的護(hù)理查房課件
- 2023年四川省樂(lè)山市中考數(shù)學(xué)試卷
評(píng)論
0/150
提交評(píng)論