¿De qué sirve agregar una clave o valor nulo a un HashMap en Java?

91

HashMap permite una clave nula y cualquier número de valores nulos. ¿Cuál es el uso de ello?

subhashis
fuente
11
"Quizás el problema no es que nada nos esté molestando, sino que nosotros lo estamos molestando".
bmargulies
3
En Guava, colecciones de Google, muchas clases no permiten nulos y el razonamiento detrás de esto es que el 95% de los casos no necesitan nulos y pueden representar errores, potencialmente difíciles de encontrar.
stivlo
Lo extraño es que ConcurrentHashMapno admite claves nulas, mientras que HashMapsí.
codepleb
2
Solo HashMap permite null :)
subhashis

Respuestas:

126

No estoy seguro de lo que está preguntando, pero si está buscando un ejemplo de cuándo uno querría usar una clave nula, los uso a menudo en mapas para representar el caso predeterminado (es decir, el valor que debe usarse si una clave determinada no está presente):

Map<A, B> foo;
A search;
B val = foo.containsKey(search) ? foo.get(search) : foo.get(null);

HashMapmaneja claves nulas especialmente (ya que no puede llamar .hashCode()a un objeto nulo), pero los valores nulos no son nada especial, se almacenan en el mapa como cualquier otra cosa

Michael Mrozek
fuente
4
Entonces, si .hashCode () no es posible en null, ¿quién decide en qué carro ingresará la clave nula?
Pacerier
26
@Pacerier Hay un método especial en HashMap( putForNullKey) que lo maneja; lo almacena en la tabla 0
Michael Mrozek
1
@MichaelMrozek su última línea B val = foo.containsKey(search) ? foo.get(search) : foo.get(null);Creo que simplemente podemos llamar al método get en la clave de búsqueda que tendrá el mismo resultado. B val = foo.get(search);¿Podría corregirme si me equivoco?
dheerajraaj
6
@ dheeraj92 Su código se establecerá valen nullsi la clave no existe; el mío lo establece en cualquier nullmapa del mapa. Ese era el punto, almaceno un valor predeterminado no nulo en la nullclave en el mapa y lo uso si la clave real no existe
Michael Mrozek
28

Un ejemplo sería el modelado de árboles. Si está utilizando un HashMap para representar una estructura de árbol, donde la clave es el padre y el valor es la lista de hijos, entonces los valores de la nullclave serían los nodos raíz.

Tony
fuente
6

Un ejemplo de uso de null valores es cuando se usa HashMapcomo caché para los resultados de una operación costosa (como una llamada a un servicio web externo) que puede devolvernull .

Poner un nullvalor en el mapa le permite distinguir entre el caso en el que la operación no se ha realizado para una clave determinada ( cache.containsKey(someKey)retornos false) y donde la operación se realizó pero devolvió un nullvalor ( cache.containsKey(someKey)retornos true, cache.get(someKey)retornos null).

Sin nullvalores, tendría que poner algún valor especial en el caché para indicar una nullrespuesta, o simplemente no almacenar en caché esa respuesta y realizar la operación cada vez.

Zorac
fuente
3

Las respuestas hasta ahora solo consideran el valor de tener una nullclave, pero la pregunta también indaga sobre any number of null values.

El beneficio de almacenar el valor nullcontra una clave en un HashMap es el mismo que en las bases de datos, etc., puede registrar una distinción entre tener un valor que está vacío (por ejemplo, cadena "") y no tener ningún valor (nulo) .

Eborbob
fuente
2

Aquí está mi único ejemplo algo artificial de un caso en el que la nullclave puede ser útil:

public class Timer {
    private static final Logger LOG = Logger.getLogger(Timer.class);
    private static final Map<String, Long> START_TIMES = new HashMap<String, Long>();

    public static synchronized void start() {
        long now = System.currentTimeMillis();
        if (START_TIMES.containsKey(null)) {
            LOG.warn("Anonymous timer was started twice without being stopped; previous timer has run for " + (now - START_TIMES.get(null).longValue()) +"ms"); 
        }
        START_TIMES.put(null, now);
    }

    public static synchronized long stop() {
        if (! START_TIMES.containsKey(null)) {
            return 0;
        }

        return printTimer("Anonymous", START_TIMES.remove(null), System.currentTimeMillis());
    }

    public static synchronized void start(String name) {
        long now = System.currentTimeMillis();
        if (START_TIMES.containsKey(name)) {
            LOG.warn(name + " timer was started twice without being stopped; previous timer has run for " + (now - START_TIMES.get(name).longValue()) +"ms"); 
        }
        START_TIMES.put(name, now);
    }

    public static synchronized long stop(String name) {
        if (! START_TIMES.containsKey(name)) {
            return 0;
        }

        return printTimer(name, START_TIMES.remove(name), System.currentTimeMillis());
    }

    private static long printTimer(String name, long start, long end) {
        LOG.info(name + " timer ran for " + (end - start) + "ms");
        return end - start;
    }
}
aroth
fuente
Si está intentando detener un temporizador que no existe, o uno que ya se detuvo, debería ser un error, no ignorado.
Financia la demanda de Monica el
@QPaysTaxes: depende de su intención. Si desea una utilidad liviana que pueda usarse fácilmente, generalmente no querrá throw Exceptiontenerla cerca. Además, no es como si intentar detener un temporizador inexistente o ya detenido fuera algo de lo que la persona que llama generalmente puede recuperarse.
aroth
1

Otro ejemplo: lo uso para agrupar datos por fecha. Pero algunos datos no tienen fecha. Puedo agruparlo con el encabezado "NoDate"

Anthone
fuente
0

Una clave nula también puede ser útil cuando el mapa almacena datos para selecciones de IU donde la clave del mapa representa un campo de bean.

Un valor de campo nulo correspondiente se representaría, por ejemplo, como "(seleccione)" en la selección de la interfaz de usuario.

Gunnar
fuente