【问题标题】:GroovyString hashCode and equals do not evaluate to same value as StringGroovyString hashCode 和 equals 的计算结果与 String 不同
【发布时间】:2013-09-26 14:04:04
【问题描述】:

最近,我在我们的代码库中处理一个错误,我发现通过 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(...) 时不产生真实的结果?这是错误/设计错误吗?或者这样做是有原因的?看起来这些方法的结果应该是兼容的,因为这些类之间的交互对程序员来说应该是无缝的。这样做的结果是代码中可能出现巨大的错误,这些错误乍一看似乎很直观,但会导致地图查找出现错误。

谢谢,

克里斯

【问题讨论】:

    标签: string map groovy


    【解决方案1】:

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

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

    如你所见

    println myString.compareTo(myGroovyString)
    

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

    Groovy 字符串不是字符串,它们是一种模板机制和完全不同的对象。这就是为什么hashCode 得到不同结果的原因——请参阅'GStrings aren't Strings' section on this page

    【讨论】:

    • +1 链接。我希望我能从您早点引用的部分中得到这句话:“对于比较或映射键,两种类型之间没有自动强制转换,因此有时需要在 GString 对象上显式调用 toString()。”这对我来说似乎仍然违反直觉......但我会接受你的回答,因为这显然在 Groovy 文档中有很好的记录,我假设他们不打算改变它。
    猜你喜欢
    • 2014-05-14
    • 1970-01-01
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    相关资源
    最近更新 更多