groovy map closures

groovy: encuentra una clave en un mapa y devuelve su valor



closures (4)

Quiero encontrar una clave específica en un mapa dado. Si se encuentra la clave, entonces quiero obtener el valor de esa clave del mapa.

Esto es lo que logré hasta ahora:

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

Esto funciona, la salida es "queso" como se esperaba. Genial, pero no quiero hacer x.value al final, y no quiero hacer if(x) . Quiero que x contenga el valor de alguna manera.

No puedo obtener el valor directamente en x como este:

def mymap = [name:"Gromit", likes:"cheese", id:1234] def x = mymap.find{ it.key == "likesZZZ" }.value println x

Como el cierre de búsqueda es nulo en este caso, esto da como resultado una excepción de apuntador nulo. Por supuesto, el fragmento de código anterior funciona cuando it.key == "likes" , pero no estoy seguro de que siempre encontraré la clave de destino en el mapa.

¿Qué es un "Groovier" y una forma segura de hacerlo en un mapa?

  • Compruebe si un mapa tiene una clave determinada,
  • Y si es así, obtenga el valor de esta clave

El objetivo de usar Maps es el acceso directo. Si está seguro de que el valor en un mapa nunca será Groovy- false , puede hacer esto:

def mymap = [name:"Gromit", likes:"cheese", id:1234] def key = "likes" if(mymap[key]) { println mymap[key] }

Sin embargo, si el valor podría ser Groovy- false , debe usar:

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

La solución más sencilla, sin embargo, si sabe que el valor no va a ser Groovy- false (o puede ignorar eso), y quiere un valor predeterminado, es así:

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

Estas tres soluciones son significativamente más rápidas que sus ejemplos, ya que no escanean todo el mapa en busca de claves. Aprovechan el diseño HashMap (o LinkedHashMap ) que hace que el acceso directo a las teclas sea casi instantáneo.


En general, esto depende de lo que contenga tu mapa. Si tiene valores nulos, las cosas pueden ser complicadas y containsKey(key) o get(key, default) deberían usarse para detectar que el elemento realmente existe. En muchos casos, el código puede ser más simple, puede definir un valor predeterminado:

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

Tenga en cuenta también que containsKey() o get() son mucho más rápidos que la configuración de un cierre para verificar el elemento mymap.find{ it.key == "likes" } . Usar el cierre solo tiene sentido si realmente haces algo más complejo allí. Por ejemplo, podrías hacer esto:

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

O con parámetros explícitos:

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


La razón por la que obtienes una Excepción del puntero nulo es porque no hay una clave como ZZZ en tu segundo ejemplo. Tratar:

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


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

?. busca nulo y no crea una excepción en Groovy. Si la clave no existe, el resultado será un org.codehaus.groovy.runtime.NullObject .