微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Groovy / Grails LinkedHashMap表现得很奇怪

我在LinkedHashMap中遇到了一些令人困惑的行为
grails 2.0.3.在grails控制台中运行以下脚本:

def m = ["smart-1":[stuff:'asdf']]
println m.getClass()

def p = [id:1]
println m."smart-$p.id"
println m["smart-$p.id"]
println m.get("smart-$p.id")

println m.'smart-1'
println m['smart-1']
println m.get('smart-1')

给出输出

class java.util.LinkedHashMap
[stuff:asdf]
[stuff:asdf]
null
[stuff:asdf]
[stuff:asdf]
[stuff:asdf]

在集成测试中,我看到了相反的行为 – 我只能这样做
使用m.get(GStringImpl)获取HashMap的内容(相反
m.get(字符串)).

这种行为是预期的还是已知的?

解决方法

第一:不要在hashmap键中使用GStrings.永远.检索项目几乎总是有问题,因为 GString is not a String(该页面上的红色框),并且没有相同的哈希值.相反,请使用以下选项之一:

def key = 'key'
['key': value]
[(key): value]
[("some $key".toString()): value]

这可确保您在使用String时始终获得结果. (因此,对于查找,也总是使用String.)

我不是百分百肯定你为什么会看到奇怪的行为,但我有一个可靠的猜测. get()方法一个Java方法,而数组样式(可能是属性样式)查找是使用getAt()实现的,这是一个Groovy(GDK)方法.我的猜测是Groovy方法知道GStrings,并处理转换,以确保你不会被绊倒.

最简单的解决方案是始终使用getAt(),而不是获取

def m = ['smart-1':[stuff:'asdf']]
println m.getClass()

def p = [id:1]
println m."smart-$p.id"
println m["smart-$p.id"]
println m.getAt("smart-$p.id")

println m.'smart-1'
println m['smart-1']
println m.getAt('smart-1')

哪个工作正常.

更好的解决方案是确保在查找值时使用字符串,如下所示:

println m.get("smart-$p.id".toString())

这也有效.我更喜欢这种方法,因为直接调用方法时,你的密钥是一个字符串就更清楚了.在使用数组样式或属性样式的访问器时,我仍然使用普通的GString,因为这是标准的Groovy语法.

In an integration test,I’m seeing the opposite behavIoUr – I can only get the content of the HashMap using m.get(GStringImpl) (as opposed m.get(String)).

这很可能是因为你的hashmap中的键是保留了一个GString.

如果GString没有任何变量,Groovy编译器会静地将其转换为String文字(更好的性能),这就是为什么上面的例子实际上使用String作为键,但查找是使用GString.

例如

"Hello $name" -> GString('Hello $name')
"Hello Bob"   -> 'Hello Bob'

最后的想法:只要你处于groovy,就不要使用get(),因为Groovy提供了更清晰的[]和属性语法.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐