2015-10-07 64 views
3

假设我们有Groovy中的地图列表,我今天注意到了一个奇怪的行为。访问地图列表具有不同的行为,具体取决于索引

List listOfMap = [[1:'b'], [1: 'c']] 
println listOfMap[1]​ 

>>> [1: c] 

这对我很有意义,因为我期望从列表中获得第二个元素。

如果我现在在List中有从String到String的地图,类似的看起来的调用表现得有点奇怪。结构与上述相同,我要求索引'a'。我希望得到一个错误,告诉我一个字符作为索引是没有意义的。

而是我得到这似乎有点混乱,我的结果:

List listOfMap = [['a':'b'], ['a': 'c']] 
println listOfMap['a'] 

>>> [b, c] 

我试图找到该文件,但没能发现任何东西。

有人可以解释使用类似结构时不同行为之间的意图。也就是说,为什么第一个例子不会返回[b,c]至少一致,尽管这在标准索引操作方面可能会更加混乱。

我会非常感谢解释行为和推理。

+2

http:// docs。groovy-lang.org/latest/html/documentation/#gpath_expressions –

+0

感谢您的回答。因此,如果我正确理解链接,listOfMap ['a']转换为listOfMap.getA(),这给我所有来自listOfMaps的a对象。但是为什么它不能一直工作呢?是否因为XML标签,如果我理解正确,GPath表达式的内容不允许使用数字或以数字开头的标签? 因此,我得到的数字作为索引通常是列表中的位置,但不是更一致地始终以相同的方式进行操作? – alexanderfranke

+0

是的,但它会打破所有列表访问索引 –

回答

4

度日指数

你的第一个例子导致调用常规categoryDefaultGroovyMethods.getAt(List<T> list, int index)。此方法返回指定索引处的项目。

def listOfMap = [ 
    [1:'b'], 
    [1: 'c'] 
] 

assert listOfMap[0] == listOfMap.getAt(0) 
assert listOfMap[0] == [1:'b'] 

assert listOfMap[1] == listOfMap.getAt(1) 
assert listOfMap[1] == [1: 'c'] 

下面是使用第二List<Map>同样的方法:

def listOfMap = [ 
    ['a':'b'], 
    ['a': 'c'] 
] 

assert listOfMap[0] == listOfMap.getAt(0) 
assert listOfMap[0] == ['a':'b'] 

assert listOfMap[1] == listOfMap.getAt(1) 
assert listOfMap[1] == ['a': 'c'] 

地产

你的第二个例子调用DefaultGroovyMethods.getAt(Collection collection, String property)获取值。这种方法...

  1. 遍历集合
  2. 获取所有包含指定属性
  3. 返回这些属性的值的项目。

的方法是用Java编写的,但Groovy的相当于是这样的:

collection.findAll { it.containsKey(property) }.collect { it.get(property) } 

确认

您可以亲眼目睹这些方法通过使用自定义类来拦截他们被称为:

class GetAtTest { 
    public static List getAt(Collection self, String property) { 
     println 'Got ya! Imitating DefaultGroovyMethods.getAt(Collection, String)...' 

     self.findAll { it.containsKey(property) }.collect { it.get(property) } 
    } 

    public static <T> T getAt(List<T> self, int idx) { 
     println 'Got ya! Imitating DefaultGroovyMethods.getAt(List<T>, int)...' 

     self.get(idx) 
    } 
} 

use(GetAtTest) { 
    println listOfMap[0] 
    ... 
    println listOfMap['a'] 
} 

https://github.com/apache/incubator-groovy/blob/master/src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java

+0

伟大的解释! –

1

Emmanuel Rosa的回答非常好。另外,DefaultGroovyMethods.java中的public static List getAt(Collection coll, String property)方法的javadoc解释了这一切。

/** 
    * Support the subscript operator for Collection. 
    * <pre class="groovyTestCase"> 
    * assert [String, Long, Integer] == ["a",5L,2]["class"] 
    * </pre> 
    * 
    * @param coll  a Collection 
    * @param property a String 
    * @return a List 
    * @since 1.0 
    */ 
    public static List getAt(Collection coll, String property) { 
     //... 
    } 
相关问题