以下に示すように、最も単純なLRUアルゴリズムは、のLinkedHashMap JDK、前記オーバーライドremoveEldestEntry(のMap.Entry)メソッドを使用することです。
Javaコード
- 輸入はjava.util.ArrayList;
- インポートのjava.util.Collection;
- インポートJawakutilklaidakedःashanap。
- 輸入java.util.concurrent.locks.Lock。
- 輸入java.util.concurrent.locks.ReentrantLock。
- 輸入java.util.Map;
- / **
- *クラス説明:キャッシュのLinkedHashMap簡単な使用は、JDKのドキュメントを参照してください、removeEldestEntry方法の詳細を実現する必要があります
- *
- * @authorデニス
- *
- * @param <K>
- * @param <V>
- * /
- パブリック クラスLRULinkedHashMap <K、Vは> のLinkedHashMap <K、V>を{延び
- 民間 最終 int型MAXCAPACITY。
- プライベート 静的な 最終 フロートDEFAULT_LOAD_FACTOR = 0.75F;
- 民間 最終ロックロック= 新しいReentrantLockの();
- 公共LRULinkedHashMap(MAXCAPACITYをINT){
- スーパー(MAXCAPACITY、DEFAULT_LOAD_FACTOR、 真の);
- this.maxCapacity = MAXCAPACITY。
- }
- @オーバーライド
- 保護された ブールremoveEldestEntry(java.util.Map.Entry <K、V>長男){
- リターンの大きさ()> MAXCAPACITY。
- }
- @オーバーライド
- パブリック ブールのcontainsKey(オブジェクトキー){
- {試します
- lock.lock();
- 返す super.containsKey(キー)。
- } 最後に{
- 施錠開錠();
- }
- }
- @オーバーライド
- パブリックVの取得(オブジェクトキー){
- {試します
- lock.lock();
- リターン super.get(キー);
- } 最後に{
- 施錠開錠();
- }
- }
- @オーバーライド
- パブリックVプット(Kキー、V値){
- {試します
- lock.lock();
- リターン super.put(キー、値);
- } 最後に{
- 施錠開錠();
- }
- }
- 公共 int型のサイズ(){
- {試します
- lock.lock();
- リターン super.size();
- } 最後に{
- 施錠開錠();
- }
- }
- 公共 のボイドをクリア(){
- {試します
- lock.lock();
- super.clear();
- } 最後に{
- 施錠開錠();
- }
- }
- パブリックコレクション<のMap.Entry <K、V >>のgetAll(){
- {試します
- lock.lock();
- 返す 新しいのArrayList <のMap.Entry <K、V >>(super.entrySet());
- } 最後に{
- 施錠開錠();
- }
- }
- }
あなたが見たソースコードのLinkedHashMapを見れば、LRUアルゴリズムでは、位置がリストの先頭に直接ヘッド位置調整に、新しいコンテンツをリストポイントの位置を調整することにより、ヒットする二重リンクリスト、この方法で実装されています最近、リストの先頭にコンテンツの移動を襲ってきた、我々は、交換する最後の位置が最低使用の場所で一覧表示する必要があります。
LRUアルゴリズムはまた、タイムスタンプへのアクセスに関連して実施され、最小カウント位置を検索と置換交換時にヒットカウンタがインクリメントされるバッファ記憶が設けられている位置カウンタをカウントすることによって達成することができます。このアルゴリズムは、明らかに、最小時間計算の位置を見つけるためのトラバースカウントはO(n)がシーンをキャッシュされた少量のデータのために適しています。私は、最小カウントがMINI_ACESSより大きい場合、アクセスタイムスタンプの組み合わせを実現し、最も古いエントリがアクセスされていないが削除されます。
Javaコード
- インポートしたjava.io.Serializable;
- 輸入はjava.util.ArrayList;
- インポートのjava.util.Collection;
- 輸入java.util.HashMapを;
- インポートするjava.util.Iterator;
- 輸入java.util.Map;
- 輸入java.util.Set;
- 輸入java.util.concurrent.atomic.AtomicInteger。
- 輸入java.util.concurrent.atomic.AtomicLong;
- 輸入java.util.concurrent.locks.Lock。
- 輸入java.util.concurrent.locks.ReentrantLock。
- / **
- *
- * @authorデニス
- 従来のLRUアルゴリズム際に小さなキャッシュの数、カウントによってのみキャッシュ:*クラス説明
- * @param <K>
- * @param <V>
- * /
- パブリック クラスLRUCache <K、V> 実装シリアライズ{
- プライベート 静的 最終 int型のDEFAULT_CAPACITY = 100;
- 保護された地図<K、ValueEntry>マップ。
- 民間 最終ロックロック= 新しいReentrantLockの();
- 民間 最終 過渡 int型のMAXCAPACITY。
- プライベート 静的な int型のMINI_ACCESS = 10;
- パブリックLRUCache(){
- この(DEFAULT_CAPACITY)。
- }
- 公共LRUCache(INT容量){
- IF(容量<= 0)
- スロー 新しい新しいのRuntimeException(「0未満ではないのバッファ容量」);
- this.maxCapacity =能力;
- this.map = 新規のHashMap <K、ValueEntry>(MAXCAPACITY)。
- }
- パブリック ブールにContainsKey(Kキー){
- {試します
- lock.lock();
- 返す this.map.containsKey(キー)。
- } 最後に{
- 施錠開錠();
- }
- }
- パブリックVプット(Kキー、V値){
- {試します
- lock.lock();
- - ((map.size()> MAXCAPACITY場合は {1)&& map.containsKey(キー)!)
- //するSystem.out.println( "スタート");
- 設定<のMap.Entry <K、ValueEntry >>エントリ= this.map.entrySet()。
- removeRencentlyLeastAccess(エントリ)。
- }
- ValueEntry valueEntry = map.put(キー、 新しいValueEntry(値));
- (valueEntry!=の場合 はnull)
- valueEntry.valueを返します。
- 他
- リターン NULL;
- } 最後に{
- 施錠開錠();
- }
- }
- / **
- *最も最近アクセスを削除します
- * /
- 保護された 無効removeRencentlyLeastAccess(
- 設定<のMap.Entry <K、ValueEntry >>エントリ){
- //使用の最小周波数
- 少なくともint型= 0;
- //最長アクセスされません
- 長い早い= 0;
- K toBeRemovedByCount = NULL;
- K toBeRemovedByTime = NULL;
- 反復子<のMap.Entry <K、ValueEntry >>それは(entries.iteratorを=)。
- IF(it.hasNext()){
- Map.Entry <K、ValueEntry> valueEntry = it.next()。
- 最低= valueEntry.getValue()count.get()。
- toBeRemovedByCount = valueEntry.getKey()。
- 最も早い= valueEntry.getValue()lastAccess.get()。
- toBeRemovedByTime = valueEntry.getKey()。
- }
- 一方、(it.hasNext()){
- Map.Entry <K、ValueEntry> valueEntry = it.next()。
- IF(valueEntry.getValue()。count.get()<最低){
- 最低= valueEntry.getValue()count.get()。
- toBeRemovedByCount = valueEntry.getKey()。
- }
- IF(valueEntry.getValue()。lastAccess.get()<最古){
- 。最も早い= valueEntry.getValue()count.get();
- toBeRemovedByTime = valueEntry.getKey()。
- }
- }
- //するSystem.out.println( "削除:" + toBeRemovedを)。
- 数が最も使用MINI_ACCESSよりも大きい場合は、//、そして最も初期のアイテムのアクセス時間を削除する(つまり、アイテムが最長にアクセスしていません)
- もし(少なくとも> MINI_ACCESS){
- map.remove(toBeRemovedByTime)。
- } 他{
- map.remove(toBeRemovedByCount)。
- }
- }
- パブリックVのGET(Kキー){
- {試します
- lock.lock();
- V値= NULL;
- ValueEntry valueEntry = map.get(キー)。
- もし(valueEntry!= NULL){
- //更新アクセスタイムスタンプ
- valueEntry.updateLastAccess();
- //更新訪問
- valueEntry.count.incrementAndGet();
- 値= valueEntry.value。
- }
- 値を返します。
- } 最後に{
- 施錠開錠();
- }
- }
- 公共 のボイドをクリア(){
- {試します
- lock.lock();
- map.clear();
- } 最後に{
- 施錠開錠();
- }
- }
- 公共 int型のサイズ(){
- {試します
- lock.lock();
- map.sizeを返します();
- } 最後に{
- 施錠開錠();
- }
- }
- パブリックコレクション<のMap.Entry <K、V >>のgetAll(){
- {試します
- lock.lock();
- 設定<K>キー= map.keySet()。
- 地図<K、V> TMP = 新規のHashMap <K、V>();
- {(鍵Kキー)のために
- tmp.put(キー、map.get(キー).VALUE)。
- }
- 返す 新しいのArrayList <のMap.Entry <K、V >>(tmp.entrySet());
- } 最後に{
- 施錠開錠();
- }
- }
- クラスValueEntryは {Serializableを実装します
- プライベートV値。
- 民間のAtomicInteger数;
- プライベートAtomicLong lastAccess。
- 公共ValueEntry(V値){
- this.value =値。
- this.count = 新規のAtomicInteger(0)。
- lastAccess = 新しいAtomicLong(System.nanoTimeの());
- }
- 公共 ボイドupdateLastAccess(){
- this.lastAccess.set(System.nanoTimeの())。
- }
- }
- }
ます。https://www.cnblogs.com/wangzehuaw/p/4318038.htmlで再現