Dictionary groovy:在映射中安全地找到键并返回其值

Dictionary groovy:在映射中安全地找到键并返回其值,dictionary,groovy,closures,Dictionary,Groovy,Closures,我想在给定的地图中找到一个特定的键。如果找到了键,那么我想从映射中获取该键的值 这就是我目前所做的: def mymap = [name:"Gromit", likes:"cheese", id:1234] def x = mymap.find{ it.key == "likes" } if(x) println x.value 这是可行的,输出是预期的“奶酪”。很好,但是我不想在最后做x.value,如果(x),我也不想做。我希望x以某种方式直接包含该值 我不能像这样将值直接输入

我想在给定的地图中找到一个特定的键。如果找到了键,那么我想从映射中获取该键的值

这就是我目前所做的:

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

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

if(x)
    println x.value
这是可行的,输出是预期的“奶酪”。很好,但是我不想在最后做
x.value
,如果(x),我也不想做
。我希望x以某种方式直接包含该值

我不能像这样将值直接输入到x中:

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

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

println x
def value = mymap[key] ?: "default"
因为在这种情况下find闭包为null,所以会导致null指针异常。当然,上面的代码片段在
it.key==“likes”
时有效,但我不确定我是否总能在映射中找到目标键

在地图上执行此操作的“更常规”和安全的方法是什么:

  • 检查地图是否有给定的密钥
  • 如果是,则获取该键的值

使用地图的关键在于直接访问。如果您确信映射中的值永远不会是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 mymap = [name:"Gromit", likes:"cheese", id:1234]

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

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

这三种解决方案都比您的示例快得多,因为它们不会扫描整个地图中的键。它们利用了
HashMap
(或
LinkedHashMap
)设计,使得直接键访问几乎是即时的。

出现空指针异常的原因是,在第二个示例中没有类似于zzz的键。尝试:

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

?。
检查null,并且不会在Groovy中创建异常。如果键不存在,结果将是一个
org.codehaus.groovy.runtime.NullObject

通常,这取决于映射包含的内容。如果它有空值,事情会变得棘手,应该使用
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
}

你忘了提到当钥匙不存在时会发生什么。我假设
null
是可以的


可以使用查询Groovy映射。所以你可以做:

def x = mymap.likes
在这种情况下,
x
将包含
mymap['likes']
的值(如果存在),否则将为null

如果您要查找的密钥(例如
'likes.key'
)本身包含一个点,则可以这样引用该密钥:

def x = mymap.'likes.key'
如果键存储在变量中,请使用如下属性表示法:

如果您不喜欢
null
,请使用来指定默认值(类似于):


现在你知道所有的秘密了

请记住,groovy映射仍然只是带有“”的Java映射,因此适用于Java的规则仍然适用于groovy。值得注意的是,界面中有一个注释,上面说:

一些映射实现对它们可能包含的键和值有限制。例如,有些实现禁止空键和值,有些实现对其键的类型有限制。尝试插入不合格的键或值会引发未检查的异常,通常是
NullPointerException
ClassCastException
。试图查询是否存在不合格的键或值可能会引发异常,或者只返回false;有些实现将展示前一种行为,有些实现将展示后一种行为。更一般地说,尝试对不合格的键或值执行操作,如果该键或值的完成不会导致将不合格的元素插入到映射中,则可能引发异常,也可能成功,具体取决于实现的选择。此类异常在该接口规范中标记为“可选”


基本上是这样的:并不是所有的映射都是相同的,所以在尝试对它们执行这些操作时,一定要知道(内部)正在处理的映射类型。对于简单的东西来说这应该不是问题,因为默认情况下Groovy使用

如果需要默认值,可以将映射定义为
defmap=[:]。那么您就不需要对默认值使用Elvis运算符。当然,这也会更新映射,所以如果你不想这样,那么Elvis就是你的方式。Key也可以用双引号引起来,例如def headers=[“Content Type”:“application/json”]正如问题中所述,我不能确定Key是否总是在映射中,所以我想要一种安全工作的方式(没有例外)即使钥匙在地图上或不在地图上。太棒了。这比我最初选择的答案更棒,更符合我的要求。这就是答案。谢谢。在那里使用封口非常昂贵。最好使用
defx=mymap.get(“likes”)?.value
def x = mymap.someKey ?: 'default value'