Подтвердить что ты не робот

Что такое структура структуры данных как хэш-таблица, но редко используемые ключи удаляются?

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

Вот несколько псевдокодов, над которыми я работаю:

class MyClass {
  private Map<Integer, Integer> cache = new HashMap<Integer, Integer>();
  public int myFunc(int n) {
    if(cache.containsKey(n))
      return cache.get(n);
    int next = . . . ; //some complicated math.  guaranteed next != n.
    int ret = 1 + myFunc(next);
    cache.put(n, ret);
    return ret;
  }
}

Случается, что есть некоторые значения n, для которых myFunc() будет называться много раз, но многие другие значения n, которые будут вычисляться только один раз. Таким образом, кеш может заполнить миллионы значений, которые больше никогда не нужны. Я бы хотел, чтобы кэш автоматически удалял элементы, которые не часто извлекаются.

Это похоже на проблему, которая должна быть решена уже, но я не уверен, что такое структура данных, которую я бы использовал для ее эффективного использования. Может ли кто-нибудь указать мне в правильном направлении?


Обновление. Я знал, что это должна быть уже проблема. Он называется LRU Cache, и его легко сделать, расширив класс LinkedHashMap. Вот код, который включает решение:

class MyClass {
  private final static int SIZE_LIMIT = 1000;
  private Map<Integer, Integer> cache =
    new LinkedHashMap<Integer, Integer>(16, 0.75f, true) {
      protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest)
      {
        return size() > SIZE_LIMIT;
      }
  };
  public int myFunc(int n) {
    if(cache.containsKey(n))
      return cache.get(n);
    int next = . . . ; //some complicated math.  guaranteed next != n.
    int ret = 1 + myFunc(next);
    cache.put(n, ret);
    return ret;
  }
}
4b9b3361

Ответ 1

Вы ищете LRUList/Map. Проверьте LinkedHashMap:

Метод removeEldestEntry(Map.Entry) может быть переопределен, чтобы наложить политику для автоматического удаления устаревших сопоставлений при добавлении новых сопоставлений на карту.

Ответ 2

Googling "Карта LRU" и "Мне повезет" дает вам следующее:

http://commons.apache.org/proper/commons-collections//javadocs/api-release/org/apache/commons/collections4/map/LRUMap.html

Реализация карты с фиксированным максимальный размер, который удаляет наименьший недавно использованная запись, если запись добавляется при заполнении.

Звучит в значительной степени на:)

Ответ 3

WeakHashMap, вероятно, не будет делать то, что вы ожидаете... внимательно прочитайте документацию и убедитесь, что вы точно знаете, что вы от слабых и сильных ссылок.

Я бы порекомендовал вам взглянуть на java.util.LinkedHashMap и использовать метод removeEldestEntry для поддержки вашего кеша. Если ваша математика очень ресурсоемкая, вы можете перемещать записи на фронт, когда они используются для обеспечения того, чтобы только неиспользуемые записи попадали в конец набора.

Ответ 4

Политика Adaptive Replacement Cache предназначена для того, чтобы одноразовые запросы не загрязняли ваш кеш. Это может быть более привлекательным, чем вы ищете, но оно прямо адресует ваши "заполнение значениями, которые больше никогда не нужны".

Ответ 5

Взгляните на WeakHashMap