GroovyString hashCode和equals的计算结果与String的值不同
最近,我在我们的代码库中处理一个bug,我发现通过字符串查找HashMap中的值会产生正确的结果,而通过GStringImpl使用“${key}”查找值会产生错误的(null)结果。以下是我在Groovy控制台中进行的测试:GroovyString hashCode和equals的计算结果与String的值不同,string,map,groovy,String,Map,Groovy,最近,我在我们的代码库中处理一个bug,我发现通过字符串查找HashMap中的值会产生正确的结果,而通过GStringImpl使用“${key}”查找值会产生错误的(null)结果。以下是我在Groovy控制台中进行的测试: def myMap = ["testString" : "value"] def testString = "testString" println myMap.get("${testString}") println myMap[testString] println "
def myMap = ["testString" : "value"]
def testString = "testString"
println myMap.get("${testString}")
println myMap[testString]
println "${testString}".getClass()
println testString.getClass()
String myString = "test"
def myGroovyString = "${myString}"
println myString.equals(myGroovyString)
println myString.hashCode()
println myGroovyString.hashCode()
println myString.compareTo(myGroovyString)
产出如下:
null
value
class org.codehaus.groovy.runtime.GStringImpl
class java.lang.String
false
3556498
3556535
0
def myMap = ["testString" : "value"] as TreeMap
现在,如果我将map的定义更改为TreeMap的实现,例如:
null
value
class org.codehaus.groovy.runtime.GStringImpl
class java.lang.String
false
3556498
3556535
0
def myMap = ["testString" : "value"] as TreeMap
我得到以下结果:
value
value
class org.codehaus.groovy.runtime.GStringImpl
class java.lang.String
false
3556498
3556535
0
我知道发生这种情况的原因可能是(我没有研究HashMap与TreeMap的实现)HashMap通过hashCode()查找键,而TreeMap将使用compareTo(…)。我的问题是,为什么String和GStringImpl在使用等于(…)时不生成相同的hashCode(),也不生成真正的结果?这是错误/设计错误吗?还是这样做是有原因的?似乎这些方法的结果应该是兼容的,因为这些类之间的交互对于程序员来说应该是无缝的。这样做的结果是,代码中可能会出现错误,这些错误起初看起来很直观,但会导致地图查找中出现错误
谢谢
Chris(Groovy中默认的
Map
类型)基于对象的hashCode
执行查找
TreeMap
对树的根执行compareTo
调用,并根据调用结果从左分支或右分支下移(如果key.compareTo(node.key)
返回0
,则返回值)
如你所见
println myString.compareTo(myGroovyString)
打印0
。这就是为什么在TreeMap
中找到该项,而不同的hashCode
就是为什么在LinkedHashMap中找不到该项的原因
Groovy字符串不是字符串,而是一种模板机制和一个完全不同的对象。这就是为什么对于hashCode
,您会得到不同的结果——有关链接,请参见+1。我希望我能更早地从您引用的部分中捕捉到这句话:“这两种类型之间没有自动强制进行比较或映射键,因此有时有必要在GString对象上显式调用toString()这对我来说似乎仍然是违反直觉的…但我会接受你的答案,因为这显然在Groovy文档中有很好的文档记录,我假设他们不打算更改它。