Groovy 使用 map 操作符

使用map最简单的操作是使用key存储对象到map中和通过key从map中获取对象。

列表4.12演示了如何进行这样的工作,从map中获取对象的一种可选方式是使用下标操作符,也许读者已经猜测到了,这基于map实现了getAt方法;另外一种可选方式是使用点语法像使用属性那样来获取对象,在后面将学习到属性的相关知识;第三种选择是使用get方法,这个方法允许传递一个缺省值,在map没有相应的key的时候允许返回这个值。

如果没有指定缺省值,null将为缺省,如果get(key,default)被调用时,key没有找到并且缺省值被返回,那么key:default对将被增加到map中。

将值分配给map时可以使用下标操作符或者点语法,在使用点语法的时候,如果key包含了特殊字符,需要使用字符串符号(单引号或者双引号)围起来,如下所示:myMap = ['a.b':1] assert myMap.'a.b' == 1如果仅仅写成myMap.a.b,在这里是不会正常工作的,这其实等价于myMap.getA().getB()。

列表4.13显示了来自map的相关使用方法,大量使用到来自JDK的java.util.Map的方法,在列表4.13中显示的equals/size/containsKey/containsValue的使用是简单易懂的。keySet方法返回一个key的set集合,set是一个像list,但不包括重复的元素,并且集合中的元素没有固定的顺序,更详细的信息请参考java.util.Set的JavaDoc,
为了比较keySet是否与给定的list中的key,在这里将这个list转换为一个set,这是通过方法toSet来实现的。

values方法返回map的值(value)的列表,由于map没有办法知道key的顺序,因此不能了解value列表的顺序,为了与预知的list中的值进行比较,在这里将两个list都转换为set。

通过调用entrySet方法可以将map转换为一个集合,这个方法返回一个实体的集合,在集合中的每一个实体都可以访问到key属性和value属性。

GDK增加了两个方法到JDK的map类型:any和every,如(1)所示,它们的作用与list中的同名方法类似:它们都返回一个Boolean值用来表示map中的任何一个(any)实体或者每一个(every)实体都满足闭包要求。

能够通过几种途径来遍历map:遍历实体,或者分别遍历key集合和value集合,由于通过keySet和entrySet返回的set是一个集合,因此能够使用for-in-collection形式的循环,列表4.14列出了一些例子。

Map的each方法接受两种形式的闭包:传递一个参数给闭包,那么这个参数就是map的一个entry;传递两个参数给闭包,那么参数就是key和value,一般来说,后者在实际工作中更方便。

注意:列表4.14在store字符串上使用了三个断言,而不是一个断言,这是因为map中实体的顺序是不可预估的。

最后,可以通过几种不同的途径来进行map内容的修改,如列表4.15所示,可以通过原始的JDK的方法来移除元素,GDK引入的新的途径如下:

通过给定一个key的集合来创建一个子map(subMap),这个子map的所有实体的key都来自这个集合;

findAll用来查找满足闭包要求的所有map实体;

find用来查找任意一个满足闭包要求的map实体,这里不像list那样查找的是第一个满足闭包要求的实体,这是因为map是没有顺序的;

collect为map的每一个实体应用闭包,返回每一个闭包应用的结果组成的list(闭包是否返回结果是可选的)。

最初的两个例子(clear和remove)是JDK的方法,其余的方法全部是GDK的方法,只有subMap方法(如(1)所示)是才出现的方法,collect/find/findAll实际上在list中已经存在,只是现在操作的是map的实体,而不是list的元素,subMap方法的功能与subList的方法类似,它通过一个key的集合来过滤原始的map来获取到一个新的map。

为了断定collect方法是期望的那样工作,重新回顾一下list中关于collect的用 法:使用every方法确保每一个实体都是一致的,collect的第二个版本是附加一个集合参数,这个版本的方法将闭包的结果加到这个集合中,避免创建临时的list。

也许读者已经看到了别的数据类型的可用方法列表,你也许没有看到为grep和switch使用的isCase方法,我们需要对map进行分类吗?如果有,可以对map的keySet或者values分别独立的进行分类。

GDK还为map类型增加了两个方法:asImmutable和asSynchronized,这两个方法使用Collections.unmodifiableMap和Collection.synchronizedMap来防止对map内容的修改和并发访问保护,更详细的信息请参考javadoc相关的主题。