【问题标题】:Java LRU cache using LinkedList使用 LinkedList 的 Java LRU 缓存
【发布时间】:2014-07-31 09:20:31
【问题描述】:

stack-overflow 的新手,所以请不要介意我的菜鸟问这个问题的方式。我正在尝试使用链表实现 LRU 缓存,我在这里看到了使用linkedHashMap 和其他数据结构的其他实现,但是对于这种情况,我正在尝试使用链表创建最佳优化版本,正如我在技术过程中被问到的那样圆。

我将这里的缓存大小限制为 3

  1. 有什么方法可以更好地优化这个 LRU 实现吗?
  2. 此外,这个实现的时间复杂度是多少?如果不考虑只是打印linkedList中的值的for循环,它会是O(N)的顺序吗?

    public class LRU {
        public static void main(String[] args) {
    
            LinkedList list = new LinkedList();
            int[] feed = { 7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1 };
            for (int i = 0; i < feed.length - 1; i++) {
                if (list.size() <= 2) {
                    list.add(feed[i]);
                    System.out.println();
                    System.out.println("Added " + feed[i]);
                    System.out.println("size of list is " + list.size());
                    System.out.print("this is list ");
                    for (int k = 0; k < list.size(); k++) {
                        System.out.print(" " + list.get(k));
                    }
                }
    
                System.out.println();
                if (list.size() >= 3) {
                    System.out.println();
                    System.out.println("feed is *" + feed[i + 1] + "*");
    
                    Integer value1 = (Integer) list.get(0);
                    Integer value2 = (Integer) list.get(1);
                    Integer value3 = (Integer) list.get(2);
                    if ((feed[i + 1] != value1) || (feed[i + 1] != value2)
                            || (feed[i + 1] != value3)) {
                        list.removeLast();
                        list.addLast(feed[i + 1]);
                        list.set(0, value2);
                        list.set(1, value3);
                        list.set(2, feed[i + 1]);
                    }
                    if (feed[i + 1] == value1) {
                        list.removeLast();
                        list.addLast(value1);
                        list.removeFirst();
                        list.addFirst(value2);
                        list.set(1, value3);
                    }
                    if (feed[i + 1] == value2) {
                        list.removeLast();
                        list.addLast(value2);
                        list.set(1, value3);
                        list.removeFirst();
                        list.addFirst(value1);
                    }
                    if (feed[i + 1] == value3) {
                        list.set(0, value1);
                        list.set(1, value2);
                    }
                }
                System.out.println("Current elements in cache at " + i);
                for (int t = 0; t < list.size(); t++) {
                    System.out.print(" " + list.get(t));
                }
                System.out.println();
            }
            System.out.println();
            System.out.println("------------------------------");
            System.out.println("current elements in cache ");
            for (int i = 0; i < list.size(); i++) {
                System.out.print(" " + list.get(i));
            }
        }
    }
    

【问题讨论】:

  • 您的程序将无法编译,因为有 3 个相同的语句,例如 --int value1 = (int) list.get(0); -- 原因:无法从 Object 转换为 int -- 更新为 -- Integer value1 = (Integer ) list.get(0);
  • @NikhilJoshi 所以我更新了对 Integer 的更改,但程序仍然无法在 mac 术语上编译它给出错误“注意:LRU.java 使用未经检查或不安全的操作。注意:使用 -Xlint 重新编译:未检查详细信息。”但是代码在 Eclipse IDE 上运行正常
  • 这些不是编译错误,而是警告。它告诉您的代码闻起来很糟糕,但编译器还是会处理它。你可以通过LinkedList&lt;Object&gt; list = new LinkedList&lt;&gt;(); 摆脱这些(寻找Java Generics 的含义)
  • @tmax,SJuan76 LinkedList 声明仅在您使用 Java-7 时才有效。否则使用 -- LinkedList list = new LinkedList();
  • 你的代码没有设计缓存对象,它描述了一个过程。你的缓存对象是什么?它的方法是什么?附带说明:您的实现看起来可以使用堆栈语义,幸运的是,LinkedList 是某种堆栈实现。

标签: java caching lru


【解决方案1】:

首先你要定义一个接口。现在我看不到你应该如何使用你的缓存或者实际上你在做什么。尝试实现以下类:

class LRUCache {
    final int size;
    Cache(int size){
        this.size = size;
    }
    void put(String key, Integer value){
        //
    }
    Integer get(String key){
        //
    }
}

编辑(回复评论):
无论问题是什么,第一步都是定义接口(我不是指 Java 接口,只是传达正在发生的事情的东西)。在您的情况下,请尝试执行此操作。

class MRU {
    final int size;
    MRU(int size){
        this.size = size;
    }

    void put(Integer value){
        //
    }

    Set<Integer> mostRecentlyUsed(){
        //
    }
}

【讨论】:

  • 我同意创建接口听起来是正确的方式,此时缓存的使用只是输入一串数字并在linkedList中保留最不常用的数字。我想可能有一种不同的方式来实现这一点,以便在将数字引用到充当缓存的链表时更有意义,如果在缓存中找不到该数字,它将向缓存中添加一个新条目,否则它将在这种情况下使用缓存
  • @tmax:添加了响应,HTH
【解决方案2】:

这是我的 LRU 缓存的链表 impl,它不会通过 leetcode 判断,因为链表花费的时间太长(你会得到 Time Limit Exceeded)。

public class LRUCache {

    private Map<Integer, Integer> blocks = new HashMap<Integer,Integer>();
    private LinkedList<Integer> bru = new LinkedList<Integer>();
    private int capacity;
    private int length;

    public LRUCache(int capacity) {
        this.capacity = capacity;
        this.length = 0;
    }

    public int get(int key) {
        Integer value = blocks.get(key);
        if (value != null) {
            bru.remove(value);
            bru.addFirst(value);
            return value;
        }
        return -1;
    }

    public void set(int key, int value) {
        if (blocks.containsKey(key)) {
            bru.remove(blocks.get(key));
            blocks.put(key, value);
        } else {
            if (length >= capacity) {
                blocks.remove(bru.removeLast());
                length--;
            }

            length++;
            blocks.put(key, value);
        }
        bru.addFirst(value);
    }
}

【讨论】:

    【解决方案3】:

    我会用

    LinkedList<Integer> list = new LinkedList<>();
    

    我会使用而不是你的实现

    if (list.size() >= 3) {
        System.out.println();
        System.out.println("feed is *" + feed[i + 1] + "*");
    
        // retrieve the next value from the feed
        Integer next = feed[i + 1];
    
        if (!list.remove(next)) {
            list.removeLast();
        }
        list.addFirst(next);
    
    }
    
    System.out.println("Current elements in cache at " + i);
    

    如果下一个值在列表中,则将其删除并作为列表中的第一个元素。

    如果下一个值不在列表中,则删除最后一个元素并将下一个值作为列表中的第一个元素。

    当您随后在列表中查找元素时,例如。 G。通过 indexOf(...) 从最新到最旧的条目搜索列表。

    【讨论】:

      猜你喜欢
      • 2015-07-19
      • 1970-01-01
      • 1970-01-01
      • 2015-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-02
      • 1970-01-01
      相关资源
      最近更新 更多