在使用Groovy编程时遇到了一个奇怪的问题:
我试图从一个HashMap中获取对象,我用Groovy的“插值”特性(即,包含占位符的双引号中的字符串)- cf。下面的例子中的key 1。后来在处理过程中,我试图使用键从该Map中获取对象,这些键是我通过简单地连接字符串而使用不同的方法创建的- cf。下面的例子中的key 2。令我惊讶的是,我无法从我的Map中获得预期的对象。
然后我把它归结为这个例子:
void testGroovyStrings() {
String foo = "foo"
String bar = "bar"
String delim = '#'
HashMap map = new HashMap();
def key1 = "${foo}${delim}${bar}" // creating key variant 1
map.put(key1, new Integer(5)) // putting some object suing the "String" just created
def key2 = foo + delim + bar; // creating key variant 2
// my expectation was that this should yield the same value as key1
// and that I would get back the object that I had entered above.
// After all the keys look identical and are treated as "equal":
System.out.println "key1: '${key1}' - key2: '${key2}' equal?:${key1 == key2}"
def obj = map.get(key2) // but this yields null ?!?
System.out.println "got object: ${obj}"
// only this gave me a clue, why this failed:
System.out.println "got object: ${key1} (${key1.getClass()}) - ${key2} (${key2.getClass()})"
}
这将产生输出:
key1: 'foo#bar' - key2: 'foo#bar' equal?:true
got object: null
got object: foo#bar (class org.codehaus.groovy.runtime.GStringImpl) - foo#bar (class java.lang.String)
很明显,HashMap的get()-方法并没有调用key-objects上的equals()-方法,而是使用了一些其他的方法,这导致了一个奇怪的现象,即当用作(Hash)Map的键时,传递“==”运算符作为相等的键并不是真正相等的。
可以通过将插值后的字符串转换为“java.lang.String”来实现这一点,如下所示:
def key1 = "${foo}${delim}${bar}".toString()
但这看起来又丑又冗长:-(
我的问题是:这是(不)工作的设计或我错过了一些(编译器)设置或有一种方法来解决这个问题?或者我应该向Groovy运行时提交一个bug?其他建议?
1条答案
按热度按时间7gs2gvoe1#
应该避免使用Groovy模板化字符串作为Map的键
在您的示例中,
key1
是一个GString(模板化Groovy String)key2
是一个String如果切换到
它应该像你期望的那样工作。
看了你说你知道的编辑:-)
这是通过设计实现的,Groovy String的一个怪癖是它们不能成为好的Map键。没有编译器设置,没有必要提出一个问题,因为已经有很多了。