À quoi sert l'ajout d'une clé ou d'une valeur nulle à un HashMap en Java?

91

HashMap autorise une clé nulle et un nombre quelconque de valeurs nulles. Quelle en est l'utilité?

subhashis
la source
11
"Peut-être que le problème n'est pas que rien ne nous dérange, mais que nous le dérangeons."
bmargulies
3
Dans Guava, les collections google, de nombreuses classes n'autorisent pas la valeur null et le raisonnement derrière cela est que 95% des cas n'ont pas besoin de null et peuvent représenter des bogues, potentiellement difficiles à trouver.
stivlo
Une chose étrange est que ConcurrentHashMapcela ne prend pas en charge les clés nulles, alors que le HashMapfait.
codepleb
2
Seul HashMap autorise null :)
subhashis

Réponses:

126

Je ne suis pas sûr de ce que vous demandez, mais si vous cherchez un exemple de cas où l'on voudrait utiliser une clé nulle, je les utilise souvent dans les cartes pour représenter le cas par défaut (c'est-à-dire la valeur à utiliser si une clé donnée n'est pas présente):

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

HashMapgère spécialement les clés nulles (car il ne peut pas appeler .hashCode()un objet nul), mais les valeurs nulles ne sont rien de spécial, elles sont stockées dans la carte comme toute autre chose

Michael Mrozek
la source
4
Donc, si .hashCode () n'est pas possible sur null, qui décide dans quel chariot la touche null entrera?
Pacerier
26
@Pacerier Il y a une méthode spéciale dans HashMap( putForNullKey) qui le gère; il le stocke dans la table 0
Michael Mrozek
1
@MichaelMrozek votre dernière ligne B val = foo.containsKey(search) ? foo.get(search) : foo.get(null);Je pense que nous pouvons simplement appeler la méthode get sur la clé de recherche qui aura le même résultat. B val = foo.get(search);pourriez-vous s'il vous plaît me corriger si je me trompe?
dheerajraaj le
6
@ dheeraj92 Votre code sera défini valsur nullsi la clé n'existe pas; le mien le définit sur n'importe quelle nullcarte sur la carte. C'était le point, je stocke une valeur non nulle par défaut à la nullclé de la carte et l'utilise si la clé réelle n'existe pas
Michael Mrozek
28

Un exemple serait la modélisation des arbres. Si vous utilisez un HashMap pour représenter une arborescence, où la clé est le parent et la valeur est la liste des enfants, les valeurs de la nullclé sont les nœuds racine.

Tony
la source
6

Un exemple d'utilisation des null valeurs est l'utilisation de a HashMapcomme cache pour les résultats d'une opération coûteuse (comme un appel à un service Web externe) qui peut retourner null.

Mettre une nullvaleur dans la carte permet alors de distinguer le cas où l'opération n'a pas été effectuée pour une clé donnée ( cache.containsKey(someKey)retourne false), et où l'opération a été effectuée mais a renvoyé une nullvaleur ( cache.containsKey(someKey)retourne true, cache.get(someKey)retourne null).

Sans nullvaleurs, vous devrez soit mettre une valeur spéciale dans le cache pour indiquer une nullréponse, soit simplement ne pas mettre en cache cette réponse du tout et effectuer l'opération à chaque fois.

Zorac
la source
3

Les réponses jusqu'à présent ne considèrent que la valeur d'une nullclé, mais la question pose également des questions any number of null values.

L'avantage de stocker la valeur par nullrapport à une clé dans un HashMap est le même que dans les bases de données, etc. - vous pouvez enregistrer une distinction entre avoir une valeur qui est vide (par exemple, une chaîne "") et ne pas avoir de valeur du tout (null) .

Eborbob
la source
2

Voici mon seul exemple quelque peu artificiel d'un cas où la nullclé peut être 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;
    }
}
aroth
la source
Si vous essayez d'arrêter un minuteur inexistant ou qui a déjà été arrêté, cela devrait être une erreur, non ignorée.
Fonder le procès de Monica le
@QPaysTaxes - Dépend de votre intention. Si vous voulez un utilitaire léger qui peut être facilement utilisé, vous ne voulez généralement pas le fairethrow Exception . En outre, ce n'est pas comme si tenter d'arrêter une minuterie inexistante ou déjà arrêtée est quelque chose dont l'appelant peut généralement récupérer.
aroth
1

Autre exemple: je l'utilise pour regrouper les données par date. Mais certaines données n'ont pas de date. Je peux le regrouper avec l'en-tête "NoDate"

Anthone
la source
0

Une clé nulle peut également être utile lorsque la carte stocke des données pour les sélections d'interface utilisateur où la clé de carte représente un champ de bean.

Une valeur de champ nulle correspondante serait par exemple représentée par "(veuillez sélectionner)" dans la sélection de l'interface utilisateur.

Gunnar
la source