Crear una caché básica en Java

Hola, para ir rompiendo el hielo vamos a empezar con algo sencillo. Imaginemos que en nuestra aplicación necesitamos acceder con frecuencia a un dato o registro que podemos identificar por un código, bien sea numérico, alfanumérico...

Como sabemos, los accesos a disco o a Base de Datos son más lentos que en memoria. Empeorémoslo imaginando que para obtener todos los datos del código necesitamos hacer varios accesos o cruzar un número elevado de tablas.

La solución a esto puede ser la creación de una caché. En este caso crearemos una caché en la que mantendremos los datos por antigüedad. En una caché propiamente dicha se almacenan un número determinado de datos (por ejemplo 100 registros). Vamos a ver como crear fácilmente una clase Java que implemente una caché de un máximo de N elementos, de forma que cuando hayamos introducido N+1, se elimine automáticamente el elemento más antiguo.


package cache;

import java.util.LinkedHashMap;
import java.util.Map;

/**
* Caché de datos implementada como LinkedHashMap.
*/

public class Cache<K, V> extends LinkedHashMap<K, V> {

/** Límite de elementos en caché. */
private int limit;

/**
* Constructor.
*
* @param limit
* Limite máximo de elementos que tendrá la caché.
*/
public Cache(int maxLimit) {
this.limit = maxLimit;
}

/**
* Elimina la entrada más antigua de la caché en el momento de introducir
* una nueva entrada, sólo cuando se ha alcanzado el límite establecido.
*/
protected boolean removeEldestEntry(Map.Entry eldest) {
return size() > this.limit;
}
}

Como veis, es tan simple como extender la clase LinkedHashMap y sobrecargar el método removeEldestEntry, de forma que cuando el número de elementos supere el límite, devuelva true. Cuando este método devuelve verdadero, automáticamente se elimina el elemento más antiguo. Este método se ejecuta internamente cada vez que se introduce algo en el Map (con put y putAll). Evidentemente si no se sobrecarga, por defecto devuelve siempre false, por lo que nunca se borraría nada.

Una vez implementada, la caché se utiliza de la misma forma que cualquier Map:


/*
* Crear una nueva cache de 100 elementos, con código Integer y
* contenido String (clave y valor pueden ser de cualquier clase).
*/
Cache <Integer, String> miCache = new Cache<Integer, String>(100);

// para guardar un dato
cache.put(2, "Juan Fernandez");

/*
* Ahora busquemos un código, suponiendo que si no lo encontramos
* debemos buscarlo por ejemplo en base de datos.
*/
int codigo = 34;
String nombre = cache.get(codigo);
if (nombre == null) {
nombre = ... /* buscar en BD */
/* una vez obtenido, lo guardamos en cache por si se vuelve a pedir. */
cache.put(codigo, nombre);
}

Espero que a alguien le sirva de algo. Simplemente añadir que yo no me he inventado nada, la documentación de la api de Java es una de las grandes bazas de este lenguaje, y si se busca un poco, se encuentra solución a muchísimos problemas: Clase LinkedHashMap

3 Comments:

  1. Tano said...
    Muy interesante... a ver si me funciona
    von_Gonsez said...
    Bueno, la idea se puede utilizar para varios sistemas con un poco de adaptacion, asi que no solo es util para java... asi que a ver si vas añadiendo mas ideas utiles.
    Juanjo Vega said...
    Muy bueno. Me has ahorrado una semana de trabajo, porque no sabía que existía esto y ya iba a meterle mano implementándolo todo a saco.

    ¡Muchas gracias!

Post a Comment