欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

LRUCache的實(shí)現(xiàn)原理及利用python實(shí)現(xiàn)的方法

 更新時(shí)間:2017年11月21日 09:45:41   作者:蒂米  
LruCache 是 Android 的一個(gè)內(nèi)部類,提供了基于內(nèi)存實(shí)現(xiàn)的緩存,而下面這篇文章主要給大家介紹了關(guān)于LRUCache的實(shí)現(xiàn)原理以及利用python實(shí)現(xiàn)的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來(lái)一起看看吧。

簡(jiǎn)介

LRU(Least Recently Used)最近最少使用,最近有時(shí)間和空間最近的歧義,所以我更喜歡叫它近期最少使用算法。它的核心思想是,如果一個(gè)數(shù)據(jù)被訪問(wèn)過(guò),我們有理由相信它在將來(lái)被訪問(wèn)的概率就越高。于是當(dāng)LRU緩存達(dá)到設(shè)定的最大值時(shí)將緩存中近期最少使用的對(duì)象移除。LRUCache內(nèi)部使用LinkedHashMap來(lái)存儲(chǔ)key-value鍵值對(duì),并將LinkedHashMap設(shè)置為訪問(wèn)順序來(lái)體現(xiàn)LRU算法。

無(wú)論是對(duì)某個(gè)key的get,還是set都算做是對(duì)該key的一次使用。當(dāng)set一個(gè)不存在的key,并且LRU Cache中key的數(shù)量超過(guò)cache size的時(shí)候,需要將使用時(shí)間距離現(xiàn)在最長(zhǎng)的那個(gè)key從LRU Cache中清除。

LRU Cache實(shí)現(xiàn)

在Java中,LRUCache是通過(guò)LinkedHashMap實(shí)現(xiàn)的。鄙人照貓畫虎,實(shí)現(xiàn)一個(gè)Python版的LRU Cache(可能和其他大神的實(shí)現(xiàn)有所區(qū)別)。

首先,需要說(shuō)明的是:

LRU Cache對(duì)象內(nèi)部會(huì)維護(hù)一個(gè) 雙端循環(huán)鏈表 的 頭節(jié)點(diǎn)

LRU Cache對(duì)象內(nèi)部會(huì)維護(hù)一個(gè)dict

內(nèi)部dict的value都是Entry對(duì)象,每個(gè)Entry對(duì)象包含:

  • key的hash_code(hash_code = hash(key),在本實(shí)現(xiàn)中,hash_code相同的不同key,會(huì)被當(dāng)作一個(gè)key來(lái)處理。因此,對(duì)于自定義類,應(yīng)該實(shí)現(xiàn)魔術(shù)方法:__hash__)
  • v - (key, value)對(duì)中的value
  • prev - 前一個(gè)對(duì)象
  • next - 后一個(gè)對(duì)象

具體實(shí)現(xiàn)是:

當(dāng)從LRU Cache中g(shù)et一個(gè)key的時(shí)候:

  • 計(jì)算該key的hash_code
  • 從內(nèi)部dict中獲取到entry
  • 將該entry移動(dòng)到 雙端循環(huán)鏈表 的 第一個(gè)位置
  • 返回entry.value

當(dāng)向LRU Cache中set一個(gè)(key, value)對(duì)的時(shí)候:

計(jì)算該key的hash_code,

從LRU Cache的內(nèi)部dict中,取出該hash_code對(duì)應(yīng)的old_entry(可能不存在),然后根據(jù)(key, value)對(duì)生成一個(gè)new_entry,之后執(zhí)行:

  • dict[hash_code] = new_entry
  • 將new_entry提到 雙端循環(huán)鏈表 的第一個(gè)位置
  • 如果old_entry存在,則從鏈表中刪除old_entry
  • 如果是新增了一個(gè)(key, value)對(duì),并且cache中key的數(shù)量超過(guò)了cache size,那么將雙端鏈表的最后一個(gè)元素刪除(該元素就是那個(gè)最近最少被使用的元素),并且從內(nèi)部dict中刪除該元素

HashMap的實(shí)現(xiàn)原理

(面試過(guò)程中也經(jīng)常會(huì)被問(wèn)到):數(shù)組和鏈表組合成的鏈表散列結(jié)構(gòu),通過(guò)hash算法,盡量將數(shù)組中的數(shù)據(jù)分布均勻,如果hashcode相同再比較equals方法,如果equals方法返回false,那么就將數(shù)據(jù)以鏈表的形式存儲(chǔ)在數(shù)組的對(duì)應(yīng)位置,并將之前在該位置的數(shù)據(jù)往鏈表的后面移動(dòng),并記錄一個(gè)next屬性,來(lái)指示后移的那個(gè)數(shù)據(jù)。

注意:數(shù)組中保存的是entry(其中保存的是鍵值)

Python實(shí)現(xiàn)

class Entry:
 def __init__(self, hash_code, v, prev=None, next=None):
 self.hash_code = hash_code
 self.v = v
 self.prev = prev
 self.next = next

 def __str__(self):
 return "Entry{hash_code=%d, v=%s}" % (
  self.hash_code, self.v)
 __repr__ = __str__

class LRUCache:
 def __init__(self, max_size):
 self._max_size = max_size
 self._dict = dict()
 self._head = Entry(None, None)
 self._head.prev = self._head
 self._head.next = self._head

 def __setitem__(self, k, v):
 try:
  hash_code = hash(k)
 except TypeError:
  raise

 old_entry = self._dict.get(hash_code)
 new_entry = Entry(hash_code, v)
 self._dict[hash_code] = new_entry

 if old_entry:
  prev = old_entry.prev
  next = old_entry.next
  prev.next = next
  next.prev = prev

 head = self._head
 head_prev = self._head.prev
 head_next = self._head.next

 head.next = new_entry
 if head_prev is head:
  head.prev = new_entry
 head_next.prev = new_entry
 new_entry.prev = head
 new_entry.next = head_next

 if not old_entry and len(self._dict) > self._max_size:
  last_one = head.prev
  last_one.prev.next = head
  head.prev = last_one.prev
  self._dict.pop(last_one.hash_code)

 def __getitem__(self, k):
 entry = self._dict[hash(k)]
 head = self._head
 head_next = head.next
 prev = entry.prev
 next = entry.next

 if entry.prev is not head:
  if head.prev is entry:
  head.prev = prev
  head.next = entry

  head_next.prev = entry
  entry.prev = head
  entry.next = head_next

  prev.next = next
  next.prev = prev

 return entry.v

 def get_dict(self):
 return self._dict

if __name__ == "__main__":
 cache = LRUCache(2)
 inner_dict = cache.get_dict()

 cache[1] = 1
 assert inner_dict.keys() == [1], "test 1"
 cache[2] = 2
 assert sorted(inner_dict.keys()) == [1, 2], "test 2"
 cache[3] = 3
 assert sorted(inner_dict.keys()) == [2, 3], "test 3"
 cache[2]
 assert sorted(inner_dict.keys()) == [2, 3], "test 4"
 assert inner_dict[hash(2)].next.v == 3
 cache[4] = 4
 assert sorted(inner_dict.keys()) == [2, 4], "test 5"
 assert inner_dict[hash(4)].v == 4, "test 6"

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • python爬取51job中hr的郵箱

    python爬取51job中hr的郵箱

    這篇文章主要為大家詳細(xì)介紹了python爬取51job中hr的郵箱的相關(guān)資料,需要的朋友可以參考下
    2016-05-05
  • python列表的增刪改查實(shí)例代碼

    python列表的增刪改查實(shí)例代碼

    下面小編就為大家分享一篇python列表的增刪改查實(shí)例代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-01-01
  • python注釋和運(yùn)算符詳解

    python注釋和運(yùn)算符詳解

    這篇文章主要為大家介紹了python注釋和運(yùn)算符,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2021-12-12
  • 詳解Python中圖像邊緣檢測(cè)算法的實(shí)現(xiàn)

    詳解Python中圖像邊緣檢測(cè)算法的實(shí)現(xiàn)

    這篇文章主要為大家詳細(xì)介紹了python中圖像邊緣檢測(cè)算法的原理及實(shí)現(xiàn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • Python命名空間詳解

    Python命名空間詳解

    這篇文章主要介紹了Python命名空間詳解,非常重要的概念,需要的朋友可以參考下
    2014-08-08
  • Flask之請(qǐng)求鉤子的實(shí)現(xiàn)

    Flask之請(qǐng)求鉤子的實(shí)現(xiàn)

    這篇文章主要介紹了Flask之請(qǐng)求鉤子的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-12-12
  • pandas將多個(gè)dataframe以多個(gè)sheet的形式保存到一個(gè)excel文件中

    pandas將多個(gè)dataframe以多個(gè)sheet的形式保存到一個(gè)excel文件中

    這篇文章主要介紹了pandas將多個(gè)dataframe以多個(gè)sheet的形式保存到一個(gè)excel文件中,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • Python3.7 讀取音頻根據(jù)文件名生成腳本的代碼

    Python3.7 讀取音頻根據(jù)文件名生成腳本的代碼

    這篇文章主要介紹了Python3.7 讀取音頻根據(jù)文件名生成字幕腳本的方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-04-04
  • Python之try無(wú)法使用全局變量的問(wèn)題解決

    Python之try無(wú)法使用全局變量的問(wèn)題解決

    當(dāng)我們使用try語(yǔ)句時(shí),如果在try中使用了全局變量,但又在except或finally中修改了這個(gè)全局變量,就會(huì)出現(xiàn)這種無(wú)法修改全局變量的情況,下面就來(lái)解決一下這個(gè)問(wèn)題,感興趣的可以了解一下
    2024-08-08
  • 深入學(xué)習(xí)Python中的裝飾器使用

    深入學(xué)習(xí)Python中的裝飾器使用

    @這個(gè)操作符讓裝飾器在Python代碼中非常醒目,而裝飾器的運(yùn)用中也包含著很多Python編程中的高級(jí)技巧,這里我們就來(lái)共同深入學(xué)習(xí)Python中的裝飾器使用
    2016-06-06

最新評(píng)論