Manejar valor nulo usando Guava MapMaker / CacheBuilder
Intento hacer una caché usando MapMaker/CacheBuilder pero no entiendo cómo manejar correctamente los valores null.
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 null, entonces se lanza una NullPointerException. No entiendo por qué el ComputingConcurrentHashMap arroja un NPE en lugar de devolver un valor nulo.
¿Cómo manejar esto correctamente ? Simplemente coger el NPE y devolver null en su lugar ? Me estoy perdiendo algo ?
3 answers
Guava intenta obligarle a evitar usar null
siempre que sea posible, porque el comportamiento inadecuado o indocumentado en presencia de null
puede causar una gran cantidad de confusión y errores. Creo que definitivamente es una buena idea evitar usar nulls siempre que sea posible, y si puedes modificar tu código para que no use null
, recomiendo encarecidamente ese enfoque en su lugar.
La respuesta a su pregunta depende críticamente de lo que un valor "nulo" realmente significa en su aplicación. Mas probablemente, significa que no hay "ningún valor" para esta clave, o "nada allí."En este caso, probablemente su mejor opción es utilizar Optional
, envolviendo valores no nulos con Optional
.de y usando Optional.absent()
en lugar de null
. Si debe convertir eso en un valor nulo o no nulo, puede usar Optional.orNull()
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-14 13:57:43
Observe cómo incluso en la declaración completa de su pregunta todavía no está claro si su intención es tener ese valor nulo almacenado en caché o no. Ya sea que CacheBuilder decidiera almacenar en caché valores nulos o no, sorprendería a muchos usuarios que esperaban lo contrario. Una vez más, null
crea ambigüedades (¡eso es lo mejor!).
Así que esto es lo que haces.
¿Es posible determinar que la respuesta será "nula" sin el gasto total de
createExpensiveGraph
? es decir, ¿hay realmente ¿solo una simple verificación de precondición? Si es así, debe hacer eso antes de preguntar a la caché en absoluto, en cuyo momento la pregunta de si el resultado debe ser almacenado en caché o no simplemente desaparece.¿Quieres almacenar en caché un valor nulo? A continuación, siga los consejos de Louis para utilizar
Optional<T>
.De lo contrario, la caché no pudo hacer su trabajo de invocar un valor correcto para la clave, y la respuesta apropiada es lanzar una excepción desde su cargador de caché (sin marcar si esto es error del programador, comprobado de otra manera). Y eso proporcionará el comportamiento que desea. Si lanzas una excepción marcada, asegúrate de usar
Cache.get
, noCache.getUnchecked
, en el otro lado.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-29 16:12:23
Ver LivingWithNullHostileCollections en el wiki de Guayaba para algunas ideas sobre cómo lidiar con esto.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-30 12:56:51