Ale*_*lex 4 grails groovy linkedhashmap
我在Grails 2.0.3中遇到了LinkedHashMap的一些令人困惑的行为.在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')
Run Code Online (Sandbox Code Playgroud)
给出输出:
class java.util.LinkedHashMap
[stuff:asdf]
[stuff:asdf]
null
[stuff:asdf]
[stuff:asdf]
[stuff:asdf]
Run Code Online (Sandbox Code Playgroud)
在集成测试中,我看到了相反的行为 - 我只能使用m.get(GStringImpl)(相反
m.get(String))获取HashMap的内容.
这种行为是预期的还是已知的?
Ove*_*ous 19
第一:不要在hashmap键中使用GStrings.永远.您几乎总是在检索项目时遇到问题,因为GString 不是 String(该页面上的红色框),并且没有相同的哈希值.相反,请使用以下选项之一:
def key = 'key'
['key': value]
[(key): value]
[("some $key".toString()): value]
Run Code Online (Sandbox Code Playgroud)
这可确保您在使用String时始终获得结果.(因此,对于查找,也总是使用String.)
我不是百分百肯定你为什么会看到奇怪的行为,但我有一个可靠的猜测.该get()方法是Java方法,而数组样式(可能是属性样式)查找是使用getAt()Groovy(GDK)方法实现的.我的猜测是Groovy方法知道GStrings,并默默处理转换,以确保你不会被绊倒.
最简单的解决方案是始终使用getAt(),而不是get:
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')
Run Code Online (Sandbox Code Playgroud)
哪个工作正常.
更好的解决方案是确保在查找值时使用字符串,如下所示:
println m.get("smart-$p.id".toString())
Run Code Online (Sandbox Code Playgroud)
这也有效.我更喜欢这种方法,因为直接调用方法时,你的密钥是一个字符串就更清楚了.在使用数组样式或属性样式的访问器时,我仍然使用普通的GString,因为这是标准的Groovy语法.
在集成测试中,我看到了相反的行为 - 我只能使用m.get(GStringImpl)获取HashMap的内容(而不是m.get(String)).
这很可能是因为你的hashmap中的键是保留了一个GString.
如果GString没有任何变量,Groovy编译器会静默地将其转换为String文字(更好的性能),这就是为什么上面的例子实际上使用String作为键,但查找是使用GString.
例如
"Hello $name" -> GString('Hello $name')
"Hello Bob" -> 'Hello Bob'
Run Code Online (Sandbox Code Playgroud)
最后的想法:只要你处于groovy中,就不要使用get(),因为Groovy提供了更清晰的[]属性语法.
| 归档时间: |
|
| 查看次数: |
6439 次 |
| 最近记录: |