Java LRU кеш с использованием LinkedList

1

новый для, поэтому, пожалуйста, не возражайте против моего способа noob спросить об этом. Я пытаюсь реализовать кэширование LRU с помощью связанного списка, я видел другие реализации здесь, используя linkedHashMap и другие структуры данных, но для этого случая я пытаюсь создать лучшую оптимизированную версию, используя связанные списки, как меня спрашивали во время технической круглый.

Я ограничил размер кэша здесь до 3

  1. Есть ли способ лучше оптимизировать эту реализацию LRU?
  2. И какова будет временная сложность для этой реализации? будет ли он порядка O (N) без учета for-loops, которые просто печатают значения в связанномList?

    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));
            }
        }
    }
    
  • 0
    Ваша программа не будет компилироваться из-за 3 одинаковых операторов, таких как - int value1 = (int) list.get (0); - Причина: невозможно преобразовать объект из объекта в int - обновить его до - Integer value1 = (Integer) list.get (0);
  • 0
    @NikhilJoshi, поэтому я обновил изменения в Integer, но программа по-прежнему не будет компилироваться по термину Mac, который выдает ошибку «Примечание. LRU.java использует непроверенные или небезопасные операции. Примечание. Однако код хорошо работает на Eclipse IDE
Показать ещё 6 комментариев
Теги:
caching
lru

3 ответа

2

Прежде всего, вы хотите определить интерфейс. Прямо сейчас я не вижу, как вы должны использовать свой кеш или на самом деле то, что вы делаете. Попробуйте реализовать следующий класс:

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

EDIT (ответ на комментарий):
Какова бы ни была проблема, первым шагом является определение интерфейса (с помощью которого я не имею в виду интерфейсы Java, просто то, что сообщает, что происходит). В этом случае попробуйте реализовать это.

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

    void put(Integer value){
        //
    }

    Set<Integer> mostRecentlyUsed(){
        //
    }
}
  • 0
    Я согласен, создание интерфейса звучит правильно, на данный момент использование кэша просто вводит строку чисел и сохраняет наименее часто используемый номер в списке связанных списков. Я предполагаю, что мог бы быть другой способ реализовать это, чтобы иметь больше смысла, где число ссылается на связанный список, который действует как кеш, и если номер не найден в кеше, он добавит новую запись в кеш, иначе это будет использовать кеш в этом случае
  • 0
    @tmax: добавлен ответ, HTH
0

Здесь мой связанный список с LRU-кешем, он не будет передавать судья-ликету, потому что связанный список занимает слишком много времени (вы получите превышение лимита времени).

открытый класс 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);
}

}

0

Я бы использовал

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);

В случае, если следующее значение находится в списке, оно удаляется и помещается в качестве первого элемента в списке.

В случае, если следующее значение отсутствует в списке, последний элемент удаляется, а следующее значение ставится как первый элемент в списке.

Когда вы затем просматриваете элементы в списке, например, с помощью indexOf (...), поиск выполняется с самой последней до самой старой записи.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню