web-dev-qa-db-fra.com

groovy: trouver une clé dans une carte en toute sécurité et renvoyer sa valeur

Je veux trouver une clé spécifique dans une carte donnée. Si la clé est trouvée, je souhaite alors obtenir la valeur de cette clé sur la carte.

C'est ce que j'ai réussi jusqu'à présent:

def mymap = [name:"Gromit", likes:"cheese", id:1234]

def x = mymap.find{ it.key == "likes" }

if(x)
    println x.value

Cela fonctionne, le résultat est "fromage" comme prévu. Génial, mais je ne veux pas faire de x.value à la fin et je ne veux pas faire de if(x). Je veux que x contienne directement la valeur en quelque sorte.

Je ne peux pas obtenir la valeur directement dans x comme ceci:

def mymap = [name:"Gromit", likes:"cheese", id:1234]

def x = mymap.find{ it.key == "likesZZZ" }.value

println x

Comme la fermeture de la recherche est nulle dans ce cas, il en résulte une exception de pointeur nulle. Bien sûr, l'extrait de code ci-dessus ne fonctionne que lorsque it.key == "likes", mais je ne suis pas sûr de pouvoir toujours trouver la clé cible dans la carte.

Qu'est-ce qu'un "Groovier" et un moyen sûr de le faire sur une carte:

  • Vérifier si une carte a une clé donnée,
  • Et si oui, obtenez la valeur de cette clé
35
nonbeing
def mymap = [name:"Gromit", id:1234]
def x = mymap.find{ it.key == "likes" }?.value
if(x)
    println "x value: ${x}"

println x.getClass().name

?. vérifie la valeur null et ne crée pas d'exception dans Groovy. Si la clé n'existe pas, le résultat sera un org.codehaus.groovy.runtime.NullObject.

14
Doris Gammenthaler

L'intérêt d'utiliser Maps est tout simplement l'accès direct. Si vous savez avec certitude que la valeur d'une carte ne sera jamais Groovy -false, procédez comme suit:

def mymap = [name:"Gromit", likes:"cheese", id:1234]
def key = "likes"

if(mymap[key]) {
    println mymap[key]
}

Toutefois, si la valeur peut potentiellement être Groovy -false, vous devez utiliser:

if(mymap.containsKey(key)) {
    println mymap[key]
}

La solution la plus simple, cependant, si vous savez que la valeur ne sera pas Groovy -false (ou que vous pouvez l'ignorer) et que vous souhaitez une valeur par défaut, est la suivante:

def value = mymap[key] ?: "default"

Ces trois solutions sont nettement plus rapides que vos exemples, car elles ne parcourent pas la carte entière pour les clés. Ils tirent parti de la conception HashMap (ou LinkedHashMap) qui rend l’accès direct à la clé presque instantané.

50
OverZealous

En général, cela dépend de ce que contient votre carte. Si elle a des valeurs nulles, les choses peuvent devenir difficiles et containsKey(key) ou get(key, default) doit être utilisé pour détecter si l'élément existe réellement. Dans de nombreux cas, le code peut devenir plus simple, vous pouvez définir une valeur par défaut:

def mymap = [name:"Gromit", likes:"cheese", id:1234]
def x1 = mymap.get('likes', '[nothing specified]')
println "x value: ${x}" }

Notez également que containsKey() ou get() sont beaucoup plus rapides que la configuration d’une fermeture pour vérifier l’élément mymap.find{ it.key == "likes" }. L'utilisation de la fermeture n'a de sens que si vous faites vraiment quelque chose de plus complexe. Vous pourriez par exemple faire ceci:

mymap.find{ // "it" is the default parameter
  if (it.key != "likes") return false
  println "x value: ${it.value}" 
  return true // stop searching
}

Ou avec des paramètres explicites:

mymap.find{ key,value ->
  (key != "likes")  return false
  println "x value: ${value}" 
  return true // stop searching
}
1
Axel Heider

Si vous obtenez une exception de pointeur nul, c'est parce qu'il n'y a pas de clé likesZZZ dans votre deuxième exemple. Essayer:

def mymap = [name:"Gromit", likes:"cheese", id:1234]
def x = mymap.find{ it.key == "likes" }.value
if(x)
    println "x value: ${x}"
0
Doris Gammenthaler