2013-08-25 47 views
1

我正在閱讀Enthuware考試模擬器的一些示例問題。我遇到了一個問題,其 的問題是這樣的這個特定的集合如何適用於特定場景?

您正在設計一個緩存對象的類。當提供對象 標識符時,它應該能夠 存儲和檢索對象。此外,這個類應該通過追蹤對象的「最後訪問時間」來工作。因此,如果其容量已滿,則它應該只刪除最長未訪問的對象。

您將使用哪個集合類來存儲對象?

給出可能的選項是

  1. HashSet的
  2. 的ArrayList
  3. LinkedHashMap的
  4. LinkedList的
  5. TreeMap的

通過模擬給出的正確答案我s的LinkedHashMap。我會引用模擬器給出的解釋 。

LinkedHashMap類按其 插入時間的順序維護元素。這個屬性可以用來構建所需的緩存 如下:

  1. 插入鍵值對你做正常,其中關鍵將是對象標識符和值將是對象被緩存。

  2. 當請求鍵時,將其從LinkedHashMap中移除,然後再次插入它。這將確保這一對標記爲插入最新的 。

  3. 如果容量已滿,請刪除第一個元素。

請注意,你不能簡單地重新插入鍵值(無第一 移除),因爲重新插入操作不會影響到對的 位置。

我的確瞭解了第一點。還有以下問題。

  1. 在第一點它說,值將被緩存的對象?緩存是如何應用的?
  2. 我無法從第二點開始理解。

有人可以向我解釋這個概念嗎?謝謝。

回答

4

我相信你應該從一點鹽的例子中拿出'緩存':它意在提供一些背景,但不完全相關。

此處的緩存可能意味着從集合中檢索值,而不是訪問數據源並從中獲取值。

關於你的第二個問題:

當請求的關鍵,從LinkedHashMap的刪除它,然後 重新插入。這將確保這一對標記爲插入最新的 。

考慮以下地圖:

ID |價值
1 | Jack
5 | John
3 |珍妮

在這種情況下Jack是第一次進入,然後JohnJenny後。 現在我們要檢索緩存的值John。如果我們想這樣做,我們首先檢索他的唯一標識符的值(5),然後我們得到對象John作爲結果。現在我們有了我們的緩存值,但是跟蹤上次訪問時間的要求尚未完成。因此我們刪除他並再次添加他,基本上將他置於最後。

ID |價值
1 | Jack
3 | Jenny
5 | John

John保持緩存,但現在他的訪問時間已更新。每當地圖已滿時,您將刪除行中的第一個項目(這基本上是最長時間內未訪問的項目)。

如果地圖的3最大尺寸,我們嘗試添加Jeff,我們得到了以下情況:

ID |價值
3 | Jenny
5 | John
7 | Jeff

第一項(Jack)和因此最近最少訪問的對象將被刪除,從而爲新對象(最近訪問)做好準備。

+0

我正要寫一個答案,然後意識到自己變得困惑。很好的解釋。 – victorantunes

+0

@Jeroen,完美的答案。非常感謝你幫助我以一個例子來解釋這個概念。我非常感謝。完美的解釋。 – benz

2

在第一點說明,該值將被緩存的對象?緩存是如何應用的?

在此處緩存對象意味着將創建的對象存儲在某些集合中,以便稍後可以檢索它們。現在,由於要求使用密鑰存儲和檢索對象,因此在此處顯然爲Map,該對象將存儲從對象的Keyobject本身的映射。

另外,LinkedHashMap是合適的,因爲它保持了插入順序。因此,您創建的第一個對象將是該地圖中的第一個對象。

當請求密鑰時,將其從LinkedHashMap中移除,然後再次插入它。這將確保這一對標記爲插入最新。

再次,看看這個要求。它說,應該刪除長期未訪問的元素。現在假設一個位於第一個位置的對象沒有被訪問很久。所以,現在當你訪問它時,你不希望仍然處於第一個位置,因爲在這種情況下,當你刪除第一個元素時,你將刪除剛纔訪問的元素。

這就是爲什麼你應該刪除元素,並將其插回,以便它放在最後。

如果容量已滿,請刪除第一個元素。

由於已經清楚,第一個元素是插入的第一個元素,它具有最早的訪問時間。因此,您應該只刪除第一個元素,如要求所示:

如果其容量已滿,則應僅刪除未被訪問的對象最長。

+0

非常感謝。你的答案總是值得稱讚的,並且易於遵循。非常感謝你。 – benz

+0

@benz。不客氣:) –

0

LinkedHashMap按照它們插入的順序存儲項目。他們使用一個來實現LRU緩存。鍵是對象標識符。這些值是要緩存的項目。地圖有一個非常快的查找時間,這是什麼使地圖緩存。查找速度快於

將項目插入到地圖中會將它們放在地圖的末尾。所以每次你讀了一些東西,你就把它拿出來放回去。然後,當你在緩存中需要更多的空間時,你會切掉第一個元素。這是最長時間沒有使用過的,因爲它一路走到前面。

2

第一步,確定您是否需要設置,地圖或列表。

  1. 列出維護順序。
  2. 地圖允許快速,基於關鍵的查找項目。
  3. 集合提供基於身份的成員資格,換句話說,沒有重複。

你可能想要按鍵查找,所以它是某種地圖。但是,你也想保持秩序。乍一看,LinkedHashMap似乎是一個勝利者,但事實並非如此。

LinkedHashMap保留了廣告訂單,並且您希望保留訪問訂單。要將一個元素扭曲到另一個元素中,您必須在訪問每個元素時刪除並添加它們。這是非常浪費的,並且受到計時問題的影響(在原子添加和讀取之間)。

您可以通過維護兩個內部數據結構來簡化兩者。

  1. 快速訪問的HashMap。
  2. 基於訪問時間快速重新排序的鏈接列表。

插入時,hashmap存儲鏈接列表節點,誰的關鍵是鏈接列表節點中存儲的數據對象的關鍵字。該節點被添加到列表的「較新」末端。

當您訪問時,哈希映射會拉起鏈接列表節點,然後將其移除並插入到鏈接列表的頭部。 (並返回數據)。

當你刪除,hashmap拉起鏈表節點,並將其從鏈接列表中刪除,並清除hashmap條目。

刪除過期條目時,從鏈接列表的舊端移除,並且不要忘記清除哈希映射條目。

通過這樣做,您已經構建了自己的LinkedHashMap類,但根據訪問時間而不是插入順序進行跟蹤。

1

他們會忽略三個非常重要的點:一起

  1. LinkedHashMap,一種機制來確定何時開始刪除對象是必要的。最簡單的一個是初始化爲最大容量的計數器availableCapacity並相應地減少/增加。另一種方法是將LinkedHashMapsize()maximumCapacity變量進行比較。
  2. LinkedHashMap(特別是其values())被假定爲包含指向緩存對象/結構的唯一指針。如果保留其他指針,則認爲它們是暫時的。
  3. 緩存將在LRU機制下進行管理。

此說,併爲您解答:

  1. 是。
  2. 根據定義,LinkedHashMap中的first項是插入的第一個(「最早的」)。如果每次使用緩存條目時都將其刪除並重新插入到映射中,則它將放置在列表的末尾,從而形成「最新」。 first將永遠是不是使用時間最長的一個。 「秒」以下,等等。這就是爲什麼從前面的元素被刪除。
+0

什麼是LRU政權? – benz

+1

@benz LRU =「最近最少使用」。 IOW中,LRU項目被移除以爲最近使用的項目騰出空間。尤其是,**只是**使用。當訪問概率不隨時間變化時,這個機制運作良好。如果連續兩次使用同一個物品的情況極其不可能,那麼相反的機制(MRU)就可以很好地工作。這是非常罕見的,但是在循環訪問的情況下可能會發生。 –