Est l'aide de java Carte.containsKey () redondant lors de l'utilisation de map.obtenir()


Je me demande depuis un certain temps s'il est permis dans les meilleures pratiques de ne pas utiliser la méthode containsKey() sur java.util.Map et de faire à la place une vérification nulle sur le résultat de get().

Ma raison d'être est qu'il semble redondant de faire la recherche de la valeur deux fois - d'abord pour le containsKey() puis à nouveau pour get().

D'autre part, il se peut que la plupart des implémentations standard de Map mettent en cache la dernière recherche ou que le compilateur puisse sinon supprimer la redondance, et que pour la lisibilité du code, il est préférable de maintenir la partie containsKey().

J'apprécierais beaucoup vos commentaires.

Author: Erik Madsen, 2013-01-30

5 answers

Certaines implémentations de Map sont autorisées à avoir des valeurs null, par exemple HashMap, dans ce cas si get(key) renvoie null cela ne garantit pas qu'il n'y a pas d'entrée dans la map associée à cette clé.

Donc, si vous voulez savoir si une carte contient une clé d'utiliser Map.containsKey. Si vous avez simplement besoin d'une valeur mappée à une clé, utilisez Map.get(key). Si cette carte permet des valeurs null, alors une valeur de retour de null n'indique pas nécessairement que la carte ne contient pas de mappage pour la clé; Dans ce cas, Map.containsKey est inutile et affecter les performances. De plus, en cas d'accès simultané à une carte (par exemple ConcurrentHashMap), après avoir testé Map.containsKey(key), il y a une chance que l'entrée soit supprimée par un autre thread avant d'appeler Map.get(key).

 98
Author: Evgeniy Dorofeev, 2018-08-27 14:11:38

Je pense qu'il est assez standard d'écrire:

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

Au Lieu de

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

Ce n'est pas moins lisible et légèrement plus efficace donc je ne vois aucune raison de ne pas le faire. Évidemment si votre carte peut contenir null, les deux options n'ont pas la même sémantique.

 39
Author: assylias, 2013-09-17 20:55:33

Comme assylias l'a indiqué, il s'agit d'une question sémantique. Généralement, La Carte.get(x) == null est ce que vous voulez, mais il y a des cas où il est important d'utiliser containsKey.

Un tel cas est un cache. Une fois, j'ai travaillé sur un problème de performance dans une application Web qui interrogeait fréquemment sa base de données à la recherche d'entités qui n'existaient pas. Lorsque j'ai étudié le code de mise en cache de ce composant, j'ai réalisé qu'il interrogeait la base de données si le cache.get(clé) == null. Si la base de données a renvoyé null (entity non trouvé), nous mettrions en cache cette clé - > mappage null.

Passer à containsKey a résolu le problème car un mappage sur une valeur null signifiait en fait quelque chose. Le mappage de clé à null avait une signification sémantique différente de celle de la clé non existante.

 4
Author: Brandon, 2013-01-30 17:29:45

Nous pouvons rendre la réponse @assylias plus lisible avec Java8 Facultatif,

Optional.ofNullable(map.get(key)).ifPresent(value -> {
     //do something with value
};)
 2
Author: Raja, 2016-06-24 14:42:43

En Java si vous vérifiez l'implémentation

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

Les deux utilisent getNode pour récupérer la correspondance, où le travail principal est effectué.

La redondance est contextuelle par exemple si vous avez un dictionnaire stocké dans une carte de hachage. Lorsque vous voulez récupérer la signification d'un mot

Faire...

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

Est redondant.

Mais si vous voulez vérifier un mot est valide ou non basé sur le dictionnaire. faire...

 return dictionary.get(word) != null;

Terminé...

 return dictionary.containsKey(word);

Est redondant.

Si vous cochez l'implémentation HashSet, qui utilise HashMap en interne, utilisez 'containsKey' dans la méthode 'contains'.

    public boolean contains(Object o) {
        return map.containsKey(o);
    }
 1
Author: asela38, 2018-06-04 12:42:09