2013-01-07 39 views
31

我想在给定的地图中找到特定的键。如果找到了密钥,那么我想从地图中获取该密钥的值。groovy:在地图上找到一个键并返回它的值

这是我管理至今:

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

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

if(x) 
    println x.value 

这工作,输出的是“奶酪”预期。太棒了,但我不想在最后做x.value,我不想做if(x)。我想要x以某种方式直接包含该值。

我不能得到的值直接进入X这样的:

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

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

println x 

因为发现封在这种情况下空,这导致空指针异常。当然,上面的代码片段在it.key == "likes"时有效,但我不确定我会在地图中始终找到目标键。

什么是“更巧妙”,安全地做到这一点在地图上的方式:

  • 检查如果地图有一个给定的键,
  • 如果是的话,得到这个关键
  • 的价值

回答

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

println x.getClass().name 

?.检查空,不Groovy创建一个例外。如果密钥不存在,结果将是org.codehaus.groovy.runtime.NullObject

+0

太棒了。这比我选择的原始答案更为贴切,更符合我的需求。标记这是答案。谢谢。 – noumenon

+3

使用封闭是非常昂贵的。在那里更好地使用'def x = mymap.get(“likes”)?. value',这样效率更高 –

46

使用地图的全部重点是直接访问。如果你肯定知道在地图的价值永远不会Groovy- false,那么你可以这样做:

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

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

然而,如果该值可能是Groovy- false,你应该使用:

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

最简单的解决方案,不过,如果你知道值不会是Groovy- false(或者你可以忽略),并希望有一个默认值,是这样的:

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

这三种解决方案都比您的示例快得多,因为它们不会扫描整个地图的密钥。他们利用HashMap(或LinkedHashMap)设计,可以使得直接访问密钥几乎是瞬间的。

+1

感谢。我完全忽略了这一点。 – noumenon

+1

如果您需要默认值,您可以将地图定义为'def map = [:]。withDefault {“Default”}'。那么你不需要使用Elvis Operator作为默认值。当然,这也会更新地图,所以如果你不想要那个,那么猫王就是你的方式。 – fish

+0

键也可以用双引号括起来,例如\t \t def headers = [“Content-Type”:“application/json”] – webjockey

0

你得到空指针异常的原因是你的第二个例子中没有关键字likesZZZ。尝试:

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

正如问题中所述,我不能确定键是否总是在地图,所以我想要一种可以安全工作的方式(无一例外),即使钥匙是或不在地图中。 – noumenon

1

通常,这取决于您的地图包含的内容。如果它有空值,事情可能会变得棘手,应该使用containsKey(key)get(key, default)来检测元素是否真的存在。在许多情况下,代码可以变得更简单,你可以定义默认值:

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

还要注意containsKey()get()比建立一个封闭检查元素mymap.find{ it.key == "likes" }快得多。如果你真的在那里做更复杂的事情,只有使用闭包才有意义。你可以例如做到这一点:

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

或者有明确的参数:

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