java - spanish - Manejar el valor nulo usando Guava MapMaker/CacheBuilder
guava maven (3)
Intento hacer un caché usando MapMaker / CacheBuilder pero no entiendo cómo manejar adecuadamente los valores nulos.
ConcurrentMap<Key, Graph> graphs = new MapMaker()
.concurrencyLevel(4)
.weakKeys()
.maximumSize(10000)
.expireAfterWrite(10, TimeUnit.MINUTES)
.makeComputingMap(
new Function<Key, Graph>() {
public Graph apply(Key key) {
return createExpensiveGraph(key);
}
});
Si el método createExpensiveGraph devuelve un valor nulo, se lanza una NullpointerException. No entiendo por qué ComputingConcurrentHashMap lanza un NPE en lugar de simplemente devolver un valor nulo.
¿Cómo manejar adecuadamente esto? ¿Solo coger la NPE y devolver el nulo en su lugar? Me estoy perdiendo de algo ?
Guava intenta forzarlo a evitar el uso de null
siempre que sea posible, ya que un comportamiento inadecuado o no documentado en presencia de null
puede causar una gran cantidad de confusión y errores. Creo que definitivamente es una buena idea evitar el uso de valores nulos siempre que sea posible, y si puede modificar su código para que no use el null
, le recomiendo este enfoque.
La respuesta a su pregunta depende críticamente de lo que realmente significa un valor "nulo" en su aplicación. Lo más probable es que signifique que no hay "ningún valor" para esta clave, o "nada allí". En este caso, probablemente su mejor Optional
usar Optional
, envolviendo valores no nulos con Optional
.of y usando Optional.absent()
lugar de null
. Si debe convertir eso en un valor nulo o no nulo, puede usar Optional.orNull()
.
Observe cómo incluso en la declaración completa de su pregunta aún no está claro si su intención es tener ese valor nulo en caché o no. Si CacheBuilder decidió almacenar o no valores nulos en caché, sorprendería a muchos usuarios que esperaban lo contrario. Una vez más, null
crea ambigüedades (¡en eso es mejor!).
Así que aquí está lo que haces.
¿Es posible determinar que la respuesta será "nula" sin el gasto total de
createExpensiveGraph
? es decir, ¿hay realmente una simple condición previa? Si es así, debes hacer eso antes de preguntar al caché, en cuyo punto la pregunta de si el resultado debería ser guardado o no desaparece.¿Quieres cachear un valor nulo? Luego sigue los consejos de Louis para usar la
Optional<T>
.De lo contrario, la memoria caché no pudo realizar su tarea de reunir un valor correcto para la clave, y la respuesta adecuada es lanzar una excepción desde su cargador de memoria caché (no se selecciona si se trata de un error del programador; de lo contrario, se verifica). Y eso te proporcionará el comportamiento que quieras. Si lanza una excepción marcada, asegúrese de usar
Cache.get
, noCache.getUnchecked
, en el otro lado.
Vea LivingWithNullHostileCollections en el wiki de Guava para obtener algunas ideas sobre cómo lidiar con esto.