2008-11-07 21 views
11

Estoy buscando una estructura de datos que funcione de manera similar a una tabla hash, pero donde la tabla tiene un límite de tamaño. Cuando el número de elementos en el hash alcanza el límite de tamaño, se debe invocar una función de eliminación selectiva para deshacerse de los pares clave/valor menos recuperados en la tabla.¿Qué es una estructura de datos similar a una tabla hash, pero las claves utilizadas con poca frecuencia se eliminan?

aquí hay algo de pseudocódigo de lo que estoy trabajando en:

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

Lo que pasa es que hay algunos valores de n para los que myFunc() será llamado un montón de veces, pero muchos otros valores de n que será solo se computa una vez Entonces la memoria caché podría llenarse con millones de valores que nunca más se necesitan. Me gustaría tener una forma para que la memoria caché elimine automáticamente los elementos que no se recuperan con frecuencia.

Esto se siente como un problema que debe resolverse ya, pero no estoy seguro de cuál es la estructura de datos que utilizaría para hacerlo de manera eficiente. ¿Alguien puede señalarme en la dirección correcta?


actualización sabía que esto tenía que ser un problema resuelto ya. Se llama LRU Cache y es fácil de hacer ampliando la clase LinkedHashMap. Aquí está el código que incorpora la solución:

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

Véase también http://stackoverflow.com/questions/224868/easy-simple-to-use-lru-cache-in-java. –

Respuesta

17

Usted está buscando un LRUList/Map. Consulte LinkedHashMap:

El método removeEldestEntry(Map.Entry) puede anularse para imponer una política para eliminar automáticamente las asignaciones caducas cuando se agregan nuevas asignaciones al mapa.

+0

Me ganaste ... –

+0

¡Gracias, esto era precisamente lo que quería! – Kip

+0

Eres bienvenido y es una clase JDK, por lo que no hay dependencias externas. – ReneS

0

Tome un vistazo a WeakHashMap

+0

Eso no está haciendo exactamente lo que quiero. Por lo que entiendo, un mapa de hash débil solo significa que la presencia de una clave en el mapa no cuenta como una referencia al objeto, por lo que el recolector de basura aún puede eliminarlo. Como uso números enteros, no hay forma de estar seguro de que esto haga lo que quiero. – Kip

1

WeakHashMap probablemente no hacer lo que se espera que ... leer la documentación cuidadosamente y asegurarse de que sabe exactamente lo que de referencias débiles y fuertes.

Yo recomendaría que eche un vistazo a java.util.LinkedHashMap y use su método removeEldestEntry para mantener su caché. Si su matemática consume muchos recursos, es posible que desee mover las entradas al frente siempre que se utilicen para garantizar que solo las entradas no utilizadas caigan al final del conjunto.

4

googlear "mapa LRU" y "voy a tener suerte" le da esto:

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

Una implementación mapa con un tamaño máximo fijo que elimina el menos usado recientemente entrada si se agrega una entrada cuando está llena.

Suena un lugar bastante mucho :)

+0

Gracias, fue uno de esos casos donde es muy fácil encontrar la respuesta si ya sabes que la respuesta es "LRU map", pero si ya sabías que no necesitarías encontrarla. :) – Kip

+0

Sí, lo siento, no estaba tratando de ser sarcástica. Toco "Me siento afortunado" por accidente, también :) –

1

La política Adaptive Replacement Cache está diseñado para mantener las solicitudes de una sola vez de contaminar la caché. Esto puede ser más elegante de lo que está buscando, pero aborda directamente su "llenado de valores que nunca se necesitan de nuevo".

Cuestiones relacionadas