访问地图列表具有不同的行为,具体取决于索引

时间:2015-10-07 11:31:56

标签: arrays arraylist groovy

假设我们在Groovy中有一个地图列表,我今天发现了一个奇怪的行为。

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

>>> [1: c]

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

如果我现在在列表中有从字符串到字符串的映射,那么类似的调用会表现得很奇怪。结构与上面相同,我请求索引' a'。我希望得到一个错误告诉我一个角色作为索引没有意义。

但相反,我得到了一个让我感到困惑的结果:

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

>>> [b, c]

我试图找到相关文档,但无法找到任何内容。

有人可以在使用类似结构时解释不同行为的意图。即,为什么第一个示例不返回[b,c]也至少是一致的,即使在标准索引操作方面可能更令人困惑。

我真的很感谢对行为和推理的解释。

2 个答案:

答案 0 :(得分:4)

按索引获取

您的第一个示例会调用Groovy category DefaultGroovyMethods.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. 返回这些属性的值。
  4. 该方法是用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

答案 1 :(得分: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) {
         //...
     }