LinkedHashMapキャッシュの実装

3300 ワード

まずLinkedHashMapのいくつかの特性を見てみましょう.通常、LinkedHashMapを新規作成し、new LinkedHashMap()を作成します.これはLinkedHashMapのデフォルトの構造方法で、このように新しいLinkedHashMapの中の要素の並べ替え方式がputの時に入る順序が後で順序も変わらない.LinkedHashMapは別の構造方法を提供しています
新LinkedHashMap<>(initialCapacity,loadFactor,accessOrder)の3つのパラメータは、LinkedHashMap初期容量(サイズではなく容量を記憶し、容量はどれだけの要素を収容できるかを示し、サイズは現在のmapに含まれる要素の個数であり、もちろん初期化時のサイズは0)、LinkedHashMapのロードファクタは一般的に0.75 f(ロードファクタとは、mapのサイズがinitialCapacity*loadFactorを超えるとmapが拡張されることを意味する)、accessOrderはtrueとしてmapがアクセス順によって要素の内部順序を調整することを示す.
LinkedHashMapのget()メソッドでは、戻り要素のほかに、アクセスされた要素をチェーンテーブルの下端に配置することもできますので、最近アクセスした要素は一番下(チェーンテーブルの下端)になります.次に例をあげます
public class Test {
	public static void main(String[] args) {

		Map map = new LinkedHashMap(5, 0.75f, true);
		
		map.put("a", "1");
		map.put("b", "2");
		map.put("c", "3");
		map.put("d", "4");
		map.put("e", "5");
		
		//  map     
		for(Map.Entry mEntry : map.entrySet()){
			System.out.println(mEntry.getKey()+","+mEntry.getValue());
		}
		
		
		map.get("b");
		map.get("d");
		
		System.out.println();
		//  map                 
		for(Map.Entry mEntry : map.entrySet()){
			System.out.println(mEntry.getKey()+","+mEntry.getValue());
		}
	}
}
出力結果:
a,1 b,2 c,3 d,4 e,5 a,1 c,3 e,5 b,2 d,4
最近アクセスした2つの要素が一番下(チェーンテーブルの下端)に走っているのがわかります.
次に、クラス継承LinkedHashMapを実装してキャッシュを実装します(linkedHashMapはスレッドセキュリティではなく、実装されたすべてのキャッシュもスレッドセキュリティではないことに注意してください).
1 LRUCacheクラス実装キャッシュの新規作成
public class LRUCache extends LinkedHashMap{

	private int capacity = 16;//        16

	public LRUCache(){
		super(16,0.75f,true);
	}
	/**
	 * @param capacity      
	 */
	public LRUCache(int capacity){
		super(16,0.75f,true);
		this.capacity = capacity;
	}
	/**
	 *             :
	 *   LinkedHashMap                        
	 */
	@Override
	public boolean removeEldestEntry(Map.Entry entry){
		//  LinkedHashMap   removeEldestEntry   ,   removeEldestEntry    
		//   size()       LinkedHashMap,   LinkedHashMap      
		return size()>capacity;
	}
}

2テストクラスを新規作成
public class Test {
	
	public static void main(String[] args) {

		LRUCache map = new LRUCache(5);
		
		map.put("a", "1");
		map.put("b", "2");
		map.put("c", "3");
		map.put("d", "4");
		map.put("e", "5");
		
		//  map     
		for(Map.Entry mEntry : map.entrySet()){
			System.out.println(mEntry.getKey()+","+mEntry.getValue());
		}
		
		map.get("b");
		map.get("d");
		map.put("f", "6");
		map.put("g", "7");
		
		System.out.println();
		//  map                 
		for(Map.Entry mEntry : map.entrySet()){
			System.out.println(mEntry.getKey()+","+mEntry.getValue());
		}
	}
}

実行結果:
a,1 b,2 c,3 d,4 e,5 e,5 b,2 d,4 f,6 g,7
結果からmapにアクセスする要素b,d後d,bがチェーンテーブルの最下層に移動し,map putがチェーンテーブルの最下層を占める2つの要素を示し,作成したキャッシュ容量が5に2つの要素を追加した後,バッファ容量を超えたため,チェーンテーブルの最上位の2つの要素aとcを削除した.