0

最近,我在我们的代码库中处理一个错误,我发现通过 String 在 HashMap 中查找一个值会产生正确的结果,而使用“${key}”通过 GStringImpl 查找一个值会产生不正确的(null)结果。以下是我在 Groovy 控制台中进行的测试:

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

现在,如果我将地图的定义更改为 TreeMap 的实现,如下所示:

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() 并且在使用 equals(...) 时不产生真实的结果?这是错误/设计错误吗?或者这样做是有原因的?看起来这些方法的结果应该是兼容的,因为这些类之间的交互对程序员来说应该是无缝的。这样做的结果是代码中出现错误的可能性很大,这些错误起初可能看起来很直观,但会导致地图查找中的错误。

谢谢,

克里斯

4

1 回答 1

2

LinkedHashMap(Groovy 中的默认Map类型)基于hashCode对象的 执行查找。

TreeMap对树的根执行compareTo调用,并根据结果从左或右分支向下走(如果key.compareTo( node.key )返回则返回值0

如你所见

println myString.compareTo(myGroovyString)

打印0。这就是为什么在 中找到该项目的原因TreeMap,不同hashCode的是为什么在 中找不到它LinkedHashMap

Groovy 字符串不是字符串,它们是一种模板机制和完全不同的对象。这就是您得到不同结果的原因hashCode——请参阅本页上的“GStrings are not Strings”部分

于 2013-09-26T14:29:34.483 回答