A che serve aggiungere una chiave o un valore null a una HashMap in Java?


91

HashMap consente una chiave null e qualsiasi numero di valori null. A cosa serve?


11
"Forse il problema non è che niente ci infastidisce, ma che lo stiamo infastidendo."
bmargulies

3
In Guava, le raccolte di Google, molte classi non consentono null e il ragionamento alla base è che il 95% dei casi non necessita di null e possono rappresentare bug, potenzialmente difficili da trovare.
stivlo

La cosa strana è che ConcurrentHashMapnon supporta le chiavi null, mentre lo HashMapfa.
codepleb

2
Solo HashMap consente null :)
subhashis

Risposte:


126

Non sono sicuro di quello che stai chiedendo, ma se stai cercando un esempio di quando si vorrebbe usare una chiave nulla, li uso spesso nelle mappe per rappresentare il caso predefinito (cioè il valore che dovrebbe essere usato se una determinata chiave non è presente):

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

HashMapgestisce le chiavi null in modo speciale (poiché non può chiamare .hashCode()su un oggetto null), ma i valori null non sono niente di speciale, sono memorizzati nella mappa come qualsiasi altra cosa


4
Quindi se .hashCode () non è possibile su null chi decide in quale carrello entrerà la chiave nulla?
Pacerier

26
@Pacerier C'è un metodo speciale in HashMap( putForNullKey) che lo gestisce; lo memorizza nella tabella 0
Michael Mrozek

1
@MichaelMrozek la tua ultima riga B val = foo.containsKey(search) ? foo.get(search) : foo.get(null);Penso che possiamo semplicemente chiamare il metodo get sulla chiave di ricerca che avrà lo stesso risultato. B val = foo.get(search);potresti correggermi se sbaglio qualcosa?
dheerajraaj

6
@ dheeraj92 Il tuo codice verrà impostato valsu nullse la chiave non esiste; il mio lo imposta su qualunque nullmappa nella mappa. Questo era il punto, memorizzo un valore predefinito non nullo nella nullchiave nella mappa e lo uso se la chiave effettiva non esiste
Michael Mrozek

28

Un esempio potrebbe essere la modellazione degli alberi. Se stai usando una HashMap per rappresentare una struttura ad albero, dove la chiave è il genitore e il valore è un elenco di figli, allora i valori per la nullchiave sarebbero i nodi radice.


6

Un esempio di utilizzo dei null valori è quando si utilizza a HashMapcome cache per i risultati di un'operazione costosa (come una chiamata a un servizio Web esterno) che potrebbe restituire null.

Mettere un nullvalore nella mappa permette quindi di distinguere tra il caso in cui l'operazione non è stata eseguita per una data chiave ( cache.containsKey(someKey)ritorni false), e dove l'operazione è stata eseguita ma ha restituito un nullvalore ( cache.containsKey(someKey)ritorni true, cache.get(someKey)ritorni null).

Senza nullvalori, dovresti inserire un valore speciale nella cache per indicare una nullrisposta, o semplicemente non memorizzare nella cache quella risposta ed eseguire l'operazione ogni volta.


3

Le risposte finora considerano solo il valore di avere una nullchiave, ma la domanda chiede anche any number of null values.

Il vantaggio di memorizzare il valore nullrispetto a una chiave in una HashMap è lo stesso dei database, ecc. Puoi registrare una distinzione tra avere un valore vuoto (ad es. Stringa "") e non avere alcun valore (null) .


2

Ecco il mio unico esempio un po 'artificioso di un caso in cui la nullchiave può essere utile:

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;
    }
}

Se stai cercando di fermare un timer inesistente, o uno che è già stato fermato, dovrebbe essere un errore, non ignorato.
Finanzia la causa di Monica il

@QPaysTaxes - Dipende dalle tue intenzioni. Se si desidera un'utilità leggera che possa essere utilizzata facilmente, generalmente non si vuole che throw Exceptionsia in giro. Inoltre, non è come tentare di fermare un timer inesistente o già interrotto è qualcosa da cui il chiamante può generalmente recuperare.
aroth

1

Un altro esempio: lo uso per raggruppare i dati per data. Ma alcuni dati non hanno una data. Posso raggrupparlo con l'intestazione "NoDate"


0

Una chiave nulla può essere utile anche quando la mappa memorizza i dati per le selezioni dell'interfaccia utente in cui la chiave della mappa rappresenta un campo bean.

Un valore di campo nullo corrispondente sarebbe ad esempio rappresentato come "(seleziona)" nella selezione dell'interfaccia utente.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.