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

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

Вот псевдокод того, над чем я работаю:

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

Ответы [ 6 ]

17 голосов
/ 07 ноября 2008

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

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

4 голосов
/ 07 ноября 2008

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

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

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

Звучит довольно много на:)

1 голос
/ 07 ноября 2008

Политика Adaptive Replace Cache разработана для предотвращения загрязнения вашего кэша разовыми запросами. Это может быть сложнее, чем вы ищете, но оно напрямую касается вашего «заполнения ценностями, которые больше никогда не нужны».

1 голос
/ 07 ноября 2008

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

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

0 голосов
/ 07 ноября 2008

Возможно, вы хотите применить политику "Наименее недавно использованные" для вашей карты. Существует простой способ сделать это поверх LinkedHashMap:

http://www.roseindia.net/java/example/java/util/LRUCacheExample.shtml

0 голосов
/ 07 ноября 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...