Was nützt es, einer HashMap in Java einen Nullschlüssel oder -wert hinzuzufügen?

91

HashMap erlaubt einen Nullschlüssel und eine beliebige Anzahl von Nullwerten. Was nützt es?

Subhashis
quelle
11
"Vielleicht ist das Problem nicht, dass uns nichts stört, sondern dass wir es stören."
Bmargulies
3
In Guava, Google-Sammlungen, erlauben viele Klassen keine Null und der Grund dafür ist, dass 95% der Fälle keine Null benötigen und Fehler darstellen können, die möglicherweise schwer zu finden sind.
Stivlo
Seltsam ist, dass ConcurrentHashMapdies keine Nullschlüssel unterstützt, während dies der HashMapFall ist.
Codepleb
2
Nur HashMap erlaubt null :)
Subhashis

Antworten:

126

Ich bin mir nicht sicher, was Sie fragen, aber wenn Sie nach einem Beispiel suchen, wann man einen Nullschlüssel verwenden möchte, verwende ich sie häufig in Karten, um den Standardfall darzustellen (dh den Wert, der verwendet werden sollte wenn ein bestimmter Schlüssel nicht vorhanden ist):

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

HashMapbehandelt Nullschlüssel speziell (da es kein .hashCode()Nullobjekt aufrufen kann ), aber Nullwerte sind nichts Besonderes, sie werden wie alles andere in der Karte gespeichert

Michael Mrozek
quelle
4
Wenn also .hashCode () für null nicht möglich ist, wer entscheidet dann, in welchen Wagen der Nullschlüssel eingegeben wird?
Pacerier
26
@Pacerier In HashMap( putForNullKey) gibt es eine spezielle Methode , die damit umgeht . es speichert es in Tabelle 0
Michael Mrozek
1
@MichaelMrozek Ihre letzte Zeile B val = foo.containsKey(search) ? foo.get(search) : foo.get(null);Ich denke, wir können einfach get-Methode auf Suchschlüssel aufrufen, die das gleiche Ergebnis haben wird. B val = foo.get(search);Könnten Sie mich bitte korrigieren, wenn ich etwas falsch mache?
Dheerajraaj
6
@ dheeraj92 Ihr Code wird auf gesetzt val, nullwenn der Schlüssel nicht vorhanden ist. meins setzt es auf die nullKarten in der Karte. Das war der Punkt, ich speichere einen Standardwert ungleich Null am nullSchlüssel in der Karte und verwende ihn, wenn der tatsächliche Schlüssel nicht existiert
Michael Mrozek
28

Ein Beispiel wäre das Modellieren von Bäumen. Wenn Sie eine HashMap verwenden, um eine Baumstruktur darzustellen, bei der der Schlüssel das übergeordnete Element und der Wert die Liste der untergeordneten Elemente ist, sind die Werte für den nullSchlüssel die Stammknoten.

Tony
quelle
6

Ein Beispiel für die Verwendung von null Werten ist die Verwendung von a HashMapals Cache für Ergebnisse einer teuren Operation (z. B. eines Aufrufs eines externen Webdienstes), die möglicherweise zurückgegeben wird null.

Wenn Sie einen nullWert in die Zuordnung einfügen, können Sie zwischen dem Fall unterscheiden, in dem die Operation für einen bestimmten Schlüssel nicht ausgeführt wurde ( cache.containsKey(someKey)Rückgabe false), und dem Fall, in dem die Operation ausgeführt wurde, aber einen nullWert zurückgegeben hat ( cache.containsKey(someKey)Rückgabe true, cache.get(someKey)Rückgabe null).

Ohne nullWerte müssten Sie entweder einen speziellen Wert in den Cache einfügen, um eine nullAntwort anzuzeigen , oder diese Antwort einfach überhaupt nicht zwischenspeichern und die Operation jedes Mal ausführen.

Zorac
quelle
3

Die bisherigen Antworten berücksichtigen nur den Wert eines nullSchlüssels, aber die Frage fragt auch nach any number of null values.

Der Vorteil des Speicherns des Werts nullfür einen Schlüssel in einer HashMap ist der gleiche wie in Datenbanken usw. - Sie können einen Unterschied zwischen einem leeren Wert (z. B. Zeichenfolge "") und einem Wert (null) aufzeichnen. .

Eborbob
quelle
2

Hier ist mein nur ein wenig erfundenes Beispiel für einen Fall, in dem der nullSchlüssel nützlich sein kann:

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
quelle
Wenn Sie versuchen, einen nicht vorhandenen oder bereits gestoppten Timer zu stoppen, sollte dies ein Fehler sein, der nicht ignoriert wird.
Fund Monica Klage
@QPaysTaxes - Hängt von Ihrer Absicht ab. Wenn Sie ein leichtes Dienstprogramm wünschen, das einfach zu verwenden ist, möchten Sie im Allgemeinen nicht in throw Exceptionder Nähe sein. Außerdem ist es nicht so, als würde der Anrufer im Allgemeinen versuchen, einen nicht vorhandenen oder bereits gestoppten Timer zu stoppen.
aroth
1

Ein weiteres Beispiel: Ich verwende es, um Daten nach Datum zu gruppieren. Einige Daten haben jedoch kein Datum. Ich kann es mit dem Header "NoDate" gruppieren

Anthone
quelle
0

Ein Nullschlüssel kann auch hilfreich sein, wenn die Karte Daten für die Auswahl der Benutzeroberfläche speichert, wobei der Kartenschlüssel ein Bean-Feld darstellt.

Ein entsprechender Nullfeldwert würde beispielsweise in der UI-Auswahl als "(bitte auswählen)" dargestellt.

Gunnar
quelle