オブジェクト(この質問の目的のために、それらは不変です)が要求オブジェクト(URLまたはaと同じくらい単純である可能性があります)に基づいて作成されるシステムを持っていますlong
。ではなく、ファクトリ メソッドで作成されnew
ます。
リクエストのオブジェクトがすでに存在する場合、代わりに既存のインスタンスへの参照を取得できれば、新しいオブジェクトのリクエストがより効率的に行われます。
UniversalCache<K, V>
その目的のために、現時点でより良い名前がないことを求めるクラスを作成しました。LruCache
X個の強参照が保持されるようにするため、およびシステムHashMap<K, SoftReference<V> >
内の他の強参照を介してまだ生きている可能性のあるすべてのオブジェクトを追跡するために(SoftReference
オブジェクトがGCにならないようにすることに依存していません'd)。
まだキャッシュにない新しいオブジェクトが作成されると、そのオブジェクトはそのキーとともにキャッシュに追加されます。キャッシュ内で検索するには、キーを使用して参照を取得し、オブジェクトへの参照がまだあるかどうかを確認します。
私が抱えている問題は、オブジェクトがガベージ コレクションされたら、これらのキー/参照のペアを削除する方法です。which returnsHashMap
の参照を検索する全体を調べたくありません。参照対象は常に利用できるとは限らないため、それを使用してキー バックを取得または生成することはできません。そのため、キーを保存し、それを使用して からペアを削除するように拡張しています。これは良い考えですか?キーにキャッシュと同じタイプの追加フィールドを持つ があります(最終的には と同じになります)。poll
null
SoftReference
HashMap
KeyedSoftReference<K,Rt>
K
Rt
V
特に、 を処理する場所ReferenceQueue
(現時点では にget
あります) と、 から取得したオブジェクトをキャストする方法についてアドバイスをお願いしますReferenceQueue.poll()
。
これは私が今まで持っているコードです:
package com.frozenkoi.oss;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.util.HashMap;
import android.util.LruCache;
public class UniversalCache<K, V> {
private final LruCache<K, V> mStrongCache;
private final HashMap<K, KeyedSoftReference<K, V> > mSoftCache;
private final ReferenceQueue<V> mRefQueue;
private static class KeyedSoftReference<K, Rt> extends SoftReference<Rt>
{
private final K mKey;
public KeyedSoftReference(K key, Rt r, ReferenceQueue<? super Rt> q)
{
super(r, q);
mKey = key;
}
public K getKey()
{
return mKey;
}
}
public UniversalCache(int strongCacheMaxItemCount)
{
mStrongCache = new LruCache<K, V>(strongCacheMaxItemCount);
mSoftCache = new HashMap<K, KeyedSoftReference<K, V> >();
mRefQueue = new ReferenceQueue<V>();
}
private void solidify(K key, V value)
{
mStrongCache.put(key, value);
}
public void put(K key, V value)
{
solidify(key, value);
mSoftCache.put(key, new KeyedSoftReference<K, V>(key, value, mRefQueue));
}
public V get(K key)
{
//if it's in Strong container, must also be in soft.
//just check in one of them
KeyedSoftReference<K,? extends V> tempRef = mSoftCache.get(key);
final V tempVal = (null!=tempRef)?tempRef.get():null;
V retVal = null;
if (null == tempVal)
{
mSoftCache.remove(key);
retVal = tempVal;
}
else
{
//if found in LruCache container, must be also in Soft one
solidify(key, tempVal);
retVal = tempVal;
}
//remove expired entries
while (null != (tempRef = (KeyedSoftReference<K,V>)mRefQueue.poll())) //Cast
{
//how to get key from val?
K tempKey = tempRef.getKey();
mSoftCache.remove(tempKey);
}
return retVal;
}
}