groovy: safely find a key in a map and return its value

nonbeing picture nonbeing · Jan 7, 2013 · Viewed 109.7k times · Source

I want to find a specific key in a given map. If the key is found, I then want to get the value of that key from the map.

This is what I managed so far:

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

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

if(x)
    println x.value

This works, the output is "cheese" as expected. Great, but I don't want to do x.value at the end, and I don't want to do if(x). I want x to directly contain the value somehow.

I can't get the value directly into x like this:

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

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

println x

Because the find closure is null in this case, this results in a Null Pointer Exception. Of course, the above code snippet works when it.key == "likes", but I am not sure that I will always find the target key in the map.

What is a "Groovier" and safe way to do this on a map:

  • Check if a map has a given key,
  • And if so, get the value of this key

Answer

OverZealous picture OverZealous · Jan 7, 2013

The whole point of using Maps is direct access. If you know for sure that the value in a map will never be Groovy-false, then you can do this:

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

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

However, if the value could potentially be Groovy-false, you should use:

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

The easiest solution, though, if you know the value isn't going to be Groovy-false (or you can ignore that), and want a default value, is like this:

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

All three of these solutions are significantly faster than your examples, because they don't scan the entire map for keys. They take advantage of the HashMap (or LinkedHashMap) design that makes direct key access nearly instantaneous.