2013-09-26 54 views
0

最近,我在我們的代碼基於一個錯誤,我發現查找一個HashMap中的值由字符串產生正確的結果,而查找由GStringImpl值使用「$ {key}」產生了一個不正確的(null)結果。下面是一個試驗我在Groovy的控制檯所做的:GroovyString hashCode和等於不計算爲相同的值作爲字符串

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(...)時不會生成真正的結果?這是一個錯誤/設計錯誤?還是這樣做是有原因的?看起來這些方法的結果應該是兼容的,因爲這些類之間的交互應該對程序員是無縫的。這樣做的結果是代碼中出現錯誤的巨大潛力,可能起初看起來很直觀,但會導致地圖查找中的錯誤。

謝謝,

克里斯

回答

2

LinkedHashMap(默認Map類型在Groovy)執行基於對象的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

+0

+1的鏈接。我希望能早些時候引用你引用的部分的引用:「兩種類型之間沒有自動強制進行比較或映射鍵的操作,所以有時需要在GString對象上顯式調用toString()。」對我來說,它似乎仍然是違反直覺的......但是我會接受你的回答,因爲這在Groovy文檔中有明顯的記錄,我假設他們不打算改變它。 –

相關問題