GroovyString hashCode和equals不计算为与String相同的值 [英] GroovyString hashCode and equals do not evaluate to same value as String

查看:642
本文介绍了GroovyString hashCode和equals不计算为与String相同的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近,我在我们的代码库中研究一个bug,我发现通过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 

class org.codehaus.groovy.runtime.GStringImpl
class java.lang.String
false
3556498
3556535
0



$ b

b $ b

  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(...)时不会生成真正的结果?这是一个错误/设计错误?还是这样做是有原因的?看起来这些方法的结果应该是兼容的,因为这些类之间的交互应该对程序员是无缝的。这样做的结果是代码中出现错误的巨大潜力,可能起初看起来很直观,但会导致地图查找中的错误。



谢谢,



Chris

解决方案

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



TreeMap 在树的根上执行 compareTo 调用,然后关闭根据此结果向左或向右分支(并返回值,如果 key.compareTo(node.key)返回 0

正如您所见

  println myString .compareTo(myGroovyString)

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



Groovy字符串不是字符串,它们是模板机制和完全不同的对象。这就是为什么你得到不同的结果 hashCode - 请参阅 'GStrings不是字符串'部分


Recently, I was working in our codebase on a bug where I found that looking up a value in a HashMap by String produced the correct result whereas looking up a value by GStringImpl using "${key}" produced an incorrect (null) result. The following is a test I did in the Groovy console:

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)

the output produced was the following:

null
value
class org.codehaus.groovy.runtime.GStringImpl
class java.lang.String
false
3556498
3556535
0

Now, if I change the definition of the map to be an implementation of TreeMap such as the following:

def myMap = ["testString" : "value"] as TreeMap

I get the following result:

value
value
class org.codehaus.groovy.runtime.GStringImpl
class java.lang.String
false
3556498
3556535
0

I understand that the reason why this happens is probably because (I did not look at the implementation of HashMap vs. TreeMap) HashMap looks up a key by hashCode() whereas TreeMap is going to use compareTo(...). My question is why do String and GStringImpl not produce the same hashCode() and not produce a true result when equals(...) is used? Is this a bug/design error? Or was this done for a reason? It seems the results of these methods should be compatible since interactions between these classes are supposed to be seamless to the programmer. The result of this is a huge potential for mistakes in code that might seem intuitive at first but results in a bug in map lookups.

Thanks,

Chris

解决方案

LinkedHashMap (the default Map type in Groovy) performs a lookup based on the hashCode of the object.

TreeMap performs a compareTo call on the root of the tree, and goes off down the left or right branch depending on the result of this (and returns the value if key.compareTo( node.key ) returns 0)

As you have seen

println myString.compareTo(myGroovyString)

prints 0. This is why the item is found in the TreeMap, and the different hashCode is why it is not found in the LinkedHashMap

Groovy Strings are not Strings, they are a templating mechanism and a completely different object. This is why you get different results for hashCode -- see the 'GStrings aren't Strings' section on this page

这篇关于GroovyString hashCode和equals不计算为与String相同的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆