Легкий, простой в использовании кеш LRU в java

Я знаю, что это просто реализовать, но я хочу повторно использовать то, что уже существует.

Проблема, которую я хочу решить, заключается в том, что я загружаю конфигурацию (из XML, поэтому я хочу их кэшировать) для разных страниц, ролей ... поэтому комбинация входных данных может значительно увеличиться (но в 99% не будет). Чтобы справиться с этим 1%, я хочу иметь максимальное количество элементов в кеше ...

Пока я знаю, что нашел org.apache.commons.collections.map.LRUMap в apache commons, и он выглядит нормально, но хочу проверить также что-то еще. Какие-нибудь рекомендации?

@Suporwski, как вы решили проблему?

Hunt 22.08.2012 14:37

@Hunt У меня есть LRUMap из общего пользования

Juraj 26.11.2012 13:36

Очень похожий вопрос и здесь

Mifeet 15.05.2016 10:49
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
69
3
62 112
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Ответ принят как подходящий

Вы можете использовать LinkedHashMap (Java 1.4+):

// Create cache
final int MAX_ENTRIES = 100;
Map cache = new LinkedHashMap(MAX_ENTRIES+1, .75F, true) {
    // This method is called just after a new entry has been added
    public boolean removeEldestEntry(Map.Entry eldest) {
        return size() > MAX_ENTRIES;
    }
};

// Add to cache
Object key = "key";
cache.put(key, object);

// Get object
Object o = cache.get(key);
if (o == null && !cache.containsKey(key)) {
    // Object not in cache. If null is not a possible value in the cache,
    // the call to cache.contains(key) is not needed
}

// If the cache is to be used by multiple threads,
// the cache must be wrapped with code to synchronize the methods
cache = (Map)Collections.synchronizedMap(cache);

Итак, я решил использовать LRUMap.

Juraj 22.10.2008 13:22

Просто примечание - обе ваши ссылки относятся к одному и тому же примеру, я думаю, что первая должна быть javadoc LHM?

JeeBee 22.10.2008 14:00

Я открыл для себя этот аспект LinkedHashMap сегодня, и удивительно, насколько он прост. Извлеченный урок: знайте свой API.

Julien Grenier 14.11.2008 07:22

Четко написанный пример (класс кэша LRU на основе java.util.LinkedHashMap), который также работает с предоставленным тестом: связь

Champ 13.04.2012 17:54

Должен ли коэффициент нагрузки действительно быть 0,75? Как будто вы никогда не хотите, чтобы карта содержала больше MAX_ENTRIES записей.

Tim P 21.03.2013 19:32

это легко использовать?

JeffCharter 02.12.2020 22:50

Это старый вопрос, но для потомков я хотел указать ConcurrentLinkedHashMap, который является потокобезопасным, в отличие от LRUMap. Использовать довольно просто:

ConcurrentMap<K, V> cache = new ConcurrentLinkedHashMap.Builder<K, V>()
    .maximumWeightedCapacity(1000)
    .build();

И в документации есть несколько хороших Примеры, например, как сделать LRU-кеш на основе размера, а не количества элементов.

Кофеин - это перезапись Java 8, которая называется Быстрее и предлагает намного больше Особенности.
Ben Manes 26.05.2015 06:24

У меня тоже была такая же проблема, и я не нашел хороших библиотек ... поэтому я создал свою.

simplelrucache обеспечивает потокобезопасное, очень простое нераспределенное кэширование LRU с поддержкой TTL. Он предоставляет две реализации

  • Параллельный на основе ConcurrentLinkedHashMap
  • Синхронизировано на основе LinkedHashMap

Вы можете найти его здесь.

Не могли бы вы выпустить свою библиотеку в Maven Central?

Jakub Jirutka 22.02.2014 04:09

Версия 1.0 теперь должна быть в центре :)

Daimon 25.02.2014 20:22

Здесь - очень простой и легкий в использовании кеш LRU в Java. Хотя это кратко и просто, но качество продукции. Код объяснен (см. README.md) и содержит несколько модульных тестов.

Вот моя реализация, которая позволяет мне хранить в памяти оптимальное количество элементов.

Дело в том, что мне не нужно отслеживать, какие объекты используются в настоящее время, поскольку я использую комбинацию LinkedHashMap для объектов MRU и WeakHashMap для объектов LRU. Таким образом, емкость кеш-памяти не меньше размера MRU плюс все, что позволяет мне хранить сборщик мусора. Каждый раз, когда объекты падают с MRU, они переходят в LRU до тех пор, пока они будут у GC.

public class Cache<K,V> {
final Map<K,V> MRUdata;
final Map<K,V> LRUdata;

public Cache(final int capacity)
{
    LRUdata = new WeakHashMap<K, V>();

    MRUdata = new LinkedHashMap<K, V>(capacity+1, 1.0f, true) {
        protected boolean removeEldestEntry(Map.Entry<K,V> entry)
        {
            if (this.size() > capacity) {
                LRUdata.put(entry.getKey(), entry.getValue());
                return true;
            }
            return false;
        };
    };
}

public synchronized V tryGet(K key)
{
    V value = MRUdata.get(key);
    if (value!=null)
        return value;
    value = LRUdata.get(key);
    if (value!=null) {
        LRUdata.remove(key);
        MRUdata.put(key, value);
    }
    return value;
}

public synchronized void set(K key, V value)
{
    LRUdata.remove(key);
    MRUdata.put(key, value);
}
}

Отличный подход. Таким образом, кеш LRU просто хранит данные, срок действия которых уже истек, из кеша MRU ограниченного размера. Это как программный кеш 2-го уровня. Хороший!

Ogre Psalm33 19.06.2015 21:53

Если данные присутствуют в LRUdata, но отсутствуют в MRUdata, может быть полезно предупреждение / подсказка для журнала приложения об увеличении размера кеша.

Mike 08.06.2016 13:26

Другие вопросы по теме