2014-12-15 41 views
12

Tôi đã cố gắng triển khai bộ nhớ cache LRU bằng LinkedHashMap. Trong tài liệu của LinkedHashMap (http://docs.oracle.com/javase/7/docs/api/java/util/LinkedHashMap.html), nó nói:Sử dụng LinkedHashMap để triển khai bộ nhớ cache LRU

Lưu ý rằng thứ tự chèn không bị ảnh hưởng nếu khóa được chèn lại vào bản đồ.

Nhưng khi tôi làm puts sau

public class LRUCache<K, V> extends LinkedHashMap<K, V> { 
    private int size; 

    public static void main(String[] args) { 
     LRUCache<Integer, Integer> cache = LRUCache.newInstance(2); 
     cache.put(1, 1); 
     cache.put(2, 2); 
     cache.put(1, 1); 
     cache.put(3, 3); 

     System.out.println(cache); 
    } 

    private LRUCache(int size) { 
     super(size, 0.75f, true); 
     this.size = size; 
    } 

    @Override 
    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) { 
     return size() > size; 
    } 

    public static <K, V> LRUCache<K, V> newInstance(int size) { 
     return new LRUCache<K, V>(size); 
    } 

} 

Đầu ra là

{1=1, 3=3} 

nào chỉ ra rằng việc tái chèn đã ảnh hưởng đến trật tự. Có ai biết giải thích nào không?

+0

Tôi tự hỏi, bạn đang làm điều đó cho một mục đích cụ thể? Bởi vì Java đã cung cấp một 'WeakHashMap' cung cấp chức năng này. https://docs.oracle.com/javase/7/docs/api/java/util/WeakHashMap.html – Jack

+0

Nếu đơn đặt hàng sẽ không bị ảnh hưởng bởi việc chèn lại. Thứ tự phải là {2 = 2, 3 = 3}, vì {1 = 1} được thêm trước và được chèn lại. –

+1

@Jack 'WeakHashMap' không làm những gì bạn [nghĩ] (https://stackoverflow.com/questions/5511279/what-is-a-weakhashmap-and-when-to-use-it). Nó không giống với [bộ nhớ cache LRU] (https://en.wikipedia.org/wiki/Cache_algorithms#Examples). – Jeffrey

Trả lời

12

Như được chỉ ra bởi @Jeffrey, bạn đang sử dụng accessOrder. Khi bạn tạo LinkedHashMap, tham số thứ ba chỉ định cách thứ tự được thay đổi.

"true for access-order, false for insertion-order" 

Đối với thực hiện chi tiết hơn về LRU, bạn có thể xem xét điều này http://www.programcreek.com/2013/03/leetcode-lru-cache-java/

+0

Cảm ơn, tài liệu rất hữu ích. –

2

Nhưng bạn không sử dụng thứ tự chèn, bạn đang sử dụng access order.

thứ tự lặp là thứ tự mà mục của nó là cuối cùng truy cập, từ gần đây ít được tiếp cận với nhiều nhất thời gian gần đây (truy cập theo đơn đặt hàng)

...

Gọi phương thức đặt hoặc nhận được truy cập vào mục nhập tương ứng

Vì vậy, đây là trạng thái bộ nhớ cache của bạn khi bạn sửa đổi bộ nhớ cache:

LRUCache<Integer, Integer> cache = LRUCache.newInstance(2); 
    cache.put(1, 1); // { 1=1 } 
    cache.put(2, 2); // { 1=1, 2=2 } 
    cache.put(1, 1); // { 2=2, 1=1 } 
    cache.put(3, 3); // { 1=1, 3=3 } 
0

Đây là thực hiện của tôi bằng cách sử dụng LinkedHashMap trong AccessOrder. Nó sẽ di chuyển phần tử truy cập mới nhất lên mặt trước, nó chỉ chịu phí O (1) vì các phần tử bên dưới được tổ chức trong danh sách được liên kết kép trong khi cũng được lập chỉ mục bởi hàm băm. Vì vậy, các hoạt động get/put/top_newest_one đều có giá O (1).

class LRUCache extends LinkedHashMap<Integer, Integer>{ 
    private int maxSize; 
    public LRUCache(int capacity) { 
     super(capacity, 0.75f, true); 
     this.maxSize = capacity; 
    } 

    //return -1 if miss 
    public int get(int key) { 
     Integer v = super.get(key); 
     return v == null ? -1 : v; 
    } 

    public void put(int key, int value) { 
     super.put(key, value); 
    } 

    @Override 
    protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) { 
     return this.size() > maxSize; //must override it if used in a fixed cache 
    } 
} 
Các vấn đề liên quan