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

后端 未结 5 1726
我寻月下人不归
我寻月下人不归 2021-02-01 12:33

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:

         


        
相关标签:
5条回答
  • 2021-02-01 13:13
    def mymap = [name:"Gromit", id:1234]
    def x = mymap.find{ it.key == "likes" }?.value
    if(x)
        println "x value: ${x}"
    
    println x.getClass().name
    

    ?. checks for null and does not create an exception in Groovy. If the key does not exist, the result will be a org.codehaus.groovy.runtime.NullObject.

    0 讨论(0)
  • 2021-02-01 13:17

    In general, this depends what your map contains. If it has null values, things can get tricky and containsKey(key) or get(key, default) should be used to detect of the element really exists. In many cases the code can become simpler you can define a default value:

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

    Note also that containsKey() or get() are much faster than setting up a closure to check the element mymap.find{ it.key == "likes" }. Using closure only makes sense if you really do something more complex in there. You could e.g. do this:

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

    Or with explicit parameters:

    mymap.find{ key,value ->
      (key != "likes")  return false
      println "x value: ${value}" 
      return true // stop searching
    }
    
    0 讨论(0)
  • 2021-02-01 13:23

    Groovy maps can be used with the property property, so you can just do:

    def x = mymap.likes
    

    If the key you are looking for (for example 'likes.key') contains a dot itself, then you can use the syntax:

    def x = mymap.'likes.key'
    
    0 讨论(0)
  • 2021-02-01 13:27

    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.

    0 讨论(0)
  • 2021-02-01 13:34

    The reason you get a Null Pointer Exception is because there is no key likesZZZ in your second example. Try:

    def mymap = [name:"Gromit", likes:"cheese", id:1234]
    def x = mymap.find{ it.key == "likes" }.value
    if(x)
        println "x value: ${x}"
    
    0 讨论(0)
提交回复
热议问题