[解決済み] LFU(Least Frequently Used)キャッシュを実装するには?
質問
LFU(Least Frequently Used)とは、コンピュータ内のメモリを管理するためのキャッシュアルゴリズムの一種である。この方法の標準的な特徴は、システムがメモリ内でブロックが参照された回数を追跡することです。キャッシュが満杯になり、さらにスペースが必要になると、システムは参照回数が最も少ないものをパージする。
オブジェクトの最近使ったキャッシュを実装するには、例えばJavaでどのような方法が良いでしょうか?
私はすでにLinkedHashMap(オブジェクトへのアクセス回数を管理する)を使用して1つを実装しました。
キャッシュが満杯になり、別のキャッシュのためのスペースを確保する必要があるとします。キャッシュには2つのオブジェクトが記録されており、それらは1回だけアクセスされる。 もう一つのオブジェクト(キャッシュにない)が複数回アクセスされていることがわかったら、どちらを削除すればいいでしょうか?
ありがとうございます。
解決方法は?
-
私によれば、最も最近使われたオブジェクトのキャッシュを実装する最良の方法は、各オブジェクトに 'latestTS' として新しい変数を含めることです。TSはタイムスタンプを意味します。
// 1970年1月1日からのミリ秒単位で現在の日時を返すスタティックメソッドです。 long latestTS = System.currentTimeMillis()。
-
ConcurrentLinkedHashMap は Concurrent Java Collections にまだ実装されていません。 (参考 Java コンカレントコレクション API ). しかし、試しに コンカレントハッシュマップ と ダブリーリンクリスト
-
このような場合、latestTS変数を宣言しておけば、latestTS変数の値に基づいて、エントリーを削除し、新しいオブジェクトを追加することができると述べましたが、いかがでしょうか。(追加された新しいオブジェクトの頻度とlatestTSを更新することを忘れないでください。)
ご指摘の通り LinkedHashMap これは、O(1)で要素にアクセスでき、また、順序のトラバーサルを得ることができるからです。 LFU Cacheについては、以下のコードをご覧ください。 (PS: 以下のコードは、タイトルにある質問、すなわち "How to implement LFU cache" に対する答えです)
import java.util.LinkedHashMap;
import java.util.Map;
public class LFUCache {
class CacheEntry
{
private String data;
private int frequency;
// default constructor
private CacheEntry()
{}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public int getFrequency() {
return frequency;
}
public void setFrequency(int frequency) {
this.frequency = frequency;
}
}
private static int initialCapacity = 10;
private static LinkedHashMap<Integer, CacheEntry> cacheMap = new LinkedHashMap<Integer, CacheEntry>();
/* LinkedHashMap is used because it has features of both HashMap and LinkedList.
* Thus, we can get an entry in O(1) and also, we can iterate over it easily.
* */
public LFUCache(int initialCapacity)
{
this.initialCapacity = initialCapacity;
}
public void addCacheEntry(int key, String data)
{
if(!isFull())
{
CacheEntry temp = new CacheEntry();
temp.setData(data);
temp.setFrequency(0);
cacheMap.put(key, temp);
}
else
{
int entryKeyToBeRemoved = getLFUKey();
cacheMap.remove(entryKeyToBeRemoved);
CacheEntry temp = new CacheEntry();
temp.setData(data);
temp.setFrequency(0);
cacheMap.put(key, temp);
}
}
public int getLFUKey()
{
int key = 0;
int minFreq = Integer.MAX_VALUE;
for(Map.Entry<Integer, CacheEntry> entry : cacheMap.entrySet())
{
if(minFreq > entry.getValue().frequency)
{
key = entry.getKey();
minFreq = entry.getValue().frequency;
}
}
return key;
}
public String getCacheEntry(int key)
{
if(cacheMap.containsKey(key)) // cache hit
{
CacheEntry temp = cacheMap.get(key);
temp.frequency++;
cacheMap.put(key, temp);
return temp.data;
}
return null; // cache miss
}
public static boolean isFull()
{
if(cacheMap.size() == initialCapacity)
return true;
return false;
}
}
関連
-
[解決済み] 警告: コンテキスト初期化中に例外が発生 - 更新の試みはキャンセルされました。
-
[解決済み] 型の不一致:ArrayListからListへの変換ができない
-
[解決済み] Apache Camelのログに簡単なテキストを記録する
-
[解決済み] SubclipseとJavaHLのインストールで頭を悩ます
-
[解決済み] 山積みされた靴下を効率よく組み合わせるには?
-
[解決済み] Java Mapの各エントリを効率的に反復処理するには?
-
[解決済み] Mavenを使用して、依存関係を持つ実行可能なJARを作成するにはどうすればよいですか?
-
[解決済み] Java で、あるコンストラクタを別のコンストラクタから呼び出すにはどうすればよいですか?
-
[解決済み] 整数の平方根が整数であるかどうかを判断する最速の方法
-
[解決済み] JavaでLRUキャッシュを実装するとしたら、どのようにしますか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] 未処理の例外タイプIOException」が表示されるのですが?
-
[解決済み] JVMフラグCMSClassUnloadingEnabledは、実際に何をするのですか?
-
[解決済み] Java - JTextFieldが空かどうかを確認する
-
[解決済み] Application startメソッドで例外が発生する。JavaFx 11
-
[解決済み] Cloneable throws CloneNotSupportedException
-
[解決済み] 警告: コンテキスト初期化中に例外が発生 - 更新の試みはキャンセルされました。
-
[解決済み] 最も近い整数への切り捨て - 私は不正をしているのでしょうか、それともこれは十分すぎるほど適切なのでしょうか?
-
[解決済み] JAVA_OPTIONS、JAVA_TOOL_OPTIONS、JAVA_OPTSの違いについて
-
[解決済み] Javaにおけるシンボリック参照
-
[解決済み] Java: getInstanceとStaticの比較