recorrer ordenado example ejemplo diccionario java performance code-readability map

ordenado - map string string java



Está usando java Map.containsKey() redundante cuando usa map.get() (5)

Algunas implementaciones de Map pueden tener valores nulos, por ejemplo, HashMap, en este caso si get(key) devuelve null , no garantiza que no haya ninguna entrada en el mapa asociado con esta clave.

Entonces, si quiere saber si un mapa contiene una clave, use Map.containsKey . Si simplemente necesita un valor asignado a una clave, use Map.get(key) . Map.containsKey será inútil y afectará el rendimiento. Además, en caso de acceso simultáneo a un mapa (por ejemplo, ConcurrentHashMap ), después de probar Map.containsKey(key) existe la posibilidad de que la entrada se elimine por otro hilo antes de llamar a Map.get(key) .

Me he estado preguntando durante algún tiempo si está permitido dentro de las mejores prácticas abstenerse de usar el método containsKey() en java.util.Map y en su lugar hacer una verificación nula del resultado de get() .

Mi razonamiento es que parece redundante realizar la búsqueda del valor dos veces: primero para containsKey() y luego nuevamente para get() .

Por otro lado, puede ser que la mayoría de las implementaciones estándar de Map guarden en caché la última búsqueda o que el compilador pueda eliminar la redundancia, y que para la legibilidad del código sea preferible mantener la parte containsKey() .

Agradecería mucho sus comentarios.


Como lo indicó assylias, esta es una pregunta semántica. Generalmente, Map.get (x) == null es lo que desea, pero hay casos en los que es importante usar containsKey.

Uno de esos casos es un caché. Una vez trabajé en un problema de rendimiento en una aplicación web que consultaba su base de datos con frecuencia en busca de entidades que no existían. Cuando estudié el código de caché para ese componente, me di cuenta de que estaba consultando la base de datos si cache.get (key) == null. Si la base de datos devolviera nulo (entidad no encontrada), almacenaríamos en caché esa clave -> mapeo nulo.

El cambio a containsKey resolvió el problema porque una asignación a un valor nulo en realidad significaba algo. La asignación de clave a nulo tenía un significado semántico diferente al de la clave que no existía.


Creo que es bastante estándar escribir:

Object value = map.get(key); if (value != null) { //do something with value }

en lugar de

if (map.containsKey(key)) { Object value = map.get(key); //do something with value }

No es menos legible y es un poco más eficiente, así que no veo ninguna razón para no hacerlo. Obviamente, si su mapa puede contener nulo, las dos opciones no tienen la misma semántica .


En Java si comprueba la implementación

public boolean containsKey(Object key) { return getNode(hash(key), key) != null; } public V get(Object key) { Node<K,V> e; return (e = getNode(hash(key), key)) == null ? null : e.value; }

ambos usan getNode para recuperar la coincidencia, donde se realiza el trabajo principal.

la redundancia es contextual, por ejemplo, si tiene un diccionario almacenado en un mapa hash. Cuando quieres recuperar el significado de una palabra

obra...

if(dictionary.containsKey(word)) { return dictionary.get(word); }

es redundante

pero si quiere verificar una palabra es válida o no se basa en el diccionario. obra...

return dictionary.get(word) != null;

encima...

return dictionary.containsKey(word);

es redundante

Si comprueba la implementación de HashSet , que usa HashMap internamente, use ''containsKey'' en el método ''contains''.

public boolean contains(Object o) { return map.containsKey(o); }


Podemos hacer que las respuestas a @assylias sean más legibles con Java8 Opcional,

Optional.ofNullable(map.get(key)).ifPresent(value -> { //do something with value };)