Мягкая ссылка LinkedHashMap в Java?

Существует ли LinkedHashMap на основе программных ссылок в Java? Если нет, есть ли у кого-нибудь фрагмент кода, который я, вероятно, смогу использовать повторно? Я обещаю ссылаться на него правильно.

Спасибо.


person His    schedule 14.05.2009    source источник
comment
Если вы планируете сделать это для чувствительного к памяти кеша, имейте в виду, что доступная память — очень плохой способ регулировать что-либо. В среде с большой кучей можно очень долго хранить устаревшие объекты, что замедляет работу в целом. Кэши на основе времени и размера намного лучше. Вас также может заинтересовать это: kdgregory.com/index.php?page= java.refobj   -  person kdgregory    schedule 14.05.2009


Ответы (3)


WeakHashMap не сохраняет порядок вставки. Таким образом, его нельзя рассматривать как прямую замену LinkedHashMap. Кроме того, запись карты освобождается только тогда, когда ключ больше недоступен. Что может быть не тем, что вы ищете.

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

package be.citobi.oneshot;

import java.lang.ref.SoftReference;
import java.util.LinkedHashMap;

public class SoftLinkedCache<K, V>
{
    private static final long serialVersionUID = -4585400640420886743L;

    private final LinkedHashMap<K, SoftReference<V>> map;

    public SoftLinkedCache(final int cacheSize)
    {
        if (cacheSize < 1)
            throw new IllegalArgumentException("cache size must be greater than 0");

        map = new LinkedHashMap<K, SoftReference<V>>()
        {
            private static final long serialVersionUID = 5857390063785416719L;

            @Override
            protected boolean removeEldestEntry(java.util.Map.Entry<K, SoftReference<V>> eldest)
            {
                return size() > cacheSize;
            }
        };
    }

    public synchronized V put(K key, V value)
    {
        SoftReference<V> previousValueReference = map.put(key, new SoftReference<V>(value));
        return previousValueReference != null ? previousValueReference.get() : null;
    }

    public synchronized V get(K key)
    {
        SoftReference<V> valueReference = map.get(key);
        return valueReference != null ? valueReference.get() : null;
    }
}
person frroland    schedule 14.05.2009

Лучшая идея, которую я видел для этого, - это обернуть LinkedHashMap так, чтобы все, что вы put в него вложили, было WeakReference.

ОБНОВЛЕНИЕ: только что просмотрел исходный код WeakHashMap, и то, как он справляется с преобразованием всего в WeakReference, при этом все еще хорошо играя с дженериками, является надежным. Вот сигнатура основного класса, которую он использует:

private static class Entry<K,V> extends WeakReference<Object> implements Map.Entry<K,V>

Я предлагаю более подробно просмотреть источник для других идеи реализации.

ОБНОВЛЕНИЕ 2: kdgregory поднимает хороший вопрос в своем комментарии - все, что я предлагаю, это убедиться, что ссылки в Map не будут препятствовать сборке мусора референта. Вам все еще нужно очистить мертвые ссылки вручную.

person Hank Gay    schedule 14.05.2009
comment
Это не совсем работает, потому что ссылки никогда не исчезнут, они просто будут очищены. И вы получите карту, полную мертвых ссылок. Если вы внимательно посмотрите на код WeakHashMap, вы увидите, что он лениво очищает мертвые ссылки (я полагаю, используя очередь ссылок). - person kdgregory; 14.05.2009

взгляните на этот пост. Он показывает, как реализовать SoftHashMap...

person pgras    schedule 14.05.2009
comment
Apache Shiro уже имеет реализацию этого метода (с одобрения) и лицензирует его под Apache v2. Он упакован с Apache [Shiro][1]. Вы можете найти документацию [здесь][2] и исходный код [здесь][3]. [1]: en.wikipedia.org/wiki/Apache_Shiro [2]: shiro.apache.org/static/1.1.0/apidocs [3]: shiro.apache.org /static/1.1.0/apidocs/src-html/org/apache/shiro/ - person DallinDyer; 05.10.2011