Groovy探索之Gpath和List的结合 更加Groovy风格的代码
??????????????? Groovy探索之Gpath和List的结合 更加Groovy风格的代码 ? ? 在使用Groovy语言的日子里,我常常都被一些Groovy的风格所惊喜着。如闭包、each等方法、Gpath、Map参数等等,等等。我不知道其他动态语言是否也具有这样的一些风格,但起码这些风格是区别于Java语言的风格。我是多年的Java程序员,遇到这些简单、易懂的风格,难免会惊喜不已。 很多的Groovy语言风格我们很容易接受,如each方法,Gpath语句。 比如,我们有了如下的一个List对象: ? ??? ? def list = [1,2,3,4] ? 我们在Groovy语言里要遍历这个list对象,我们肯定会轻松的使用下面的each方法: ? ??? ? list.each{ ?????? ? println it ??? ? } ? 而不会使用下面的for循环: ? ??? ? for(int it in list) ??? ? { ?????? ? println it ??? ? } ??? ? 这些都是非常简单和明了的,就像我们会使用了Gpath语句,谁还会使用对于Bean对象的属性操作的"set"和"get"方法呢? 但是有一些Groovy语言风格的代码,却不是那么容易写得出来,特别是对于我们这些Java程序员来说。 但是,我们一旦学会的那些Groovy语言风格的代码,却会给我们带来更大、更多的惊喜。而这些本文所要说到的。 正如标题所言,我们今天要说到的Groovy语言风格的代码,是结合了List对象的一些方法和Gpath语句的代码。 ? 比如,我们有如下的一个Map对象,用来表示一些城市和她们所在的国家: ? ? ??? ? def cities = ['Shanghai':'China','New York':'USA','Pairs':'France','Beijing':'China'] ? 现在,我们想知道在这个Map对象中,所在国为中国的城市有哪些?在Java语言中,我们会毫不犹豫的写出如下的代码: ? ??? ? def citiesInChina = [] ??? ? cities.each{ ?????? ? if(it.value=='China') ?????? ? { ?????????? ? citiesInChina << it.key ?????? ? } ??? ? } ??? ? ??? ? println citiesInChina ??? 而在Groovy语言中,我们的具有Groovy语言风格的代码应该是如下的形式: ??? ? ??? ? def citiesInChina = cities.findAll{ ?????? ? it.value == 'China' ??? ? }.collect{it.key} ??? ? ??? ? ??? ? ??? ? println citiesInChina ??? 从上面的代码,我们可以初步的看到集合方法和Gpath结合起来的代码风格的威力。但这还不是最经典的例子。 比如我们有如下的一些GroovyBean: ? class Book { ??? ??? String name ??? ??? List authors ? ? } ? class Author { ??? ??? String name ??? ??? Address addr ? ? ? } ? class Address { ??? ??? String province ??? ??? String city ? } 上面的GroovBean的层次结构有点复杂,简单说来就是:一本书有一个或多个作者,每一个作者又都有属于自己的地址。现在,我们有如下的一个初始化数据: ?????? ?????? def addr1 = new Address(province:'Guangdong',city:'Shenzhen') ?????? def addr2 = new Address(province:'Gunagdong',city:'Guangzhou') ?????? def addr3 = new Address(province:'Hunan',city:'Changsha') ?????? def addr4 = new Address(province:'Hubei',city:'Wuhan') ?????? ?????? def books = [new Book(name:'A glance at Java',authors:[new Author(name:'Tom',addr:addr1)]), ?????? ???????????? new Book(name:'Deep into Groovy',addr:addr1),new Author(name:'Mike',addr:addr3)]), ?????? ???????????? new Book(name:'A compare of Struts and Grails',authors:[new Author(name:'Wallace',addr:addr4),new Author(name:'Bill',addr:addr2)]), ?????? ???????????? new Book(name:'learning from Groovy to Grails',addr:addr3)])] ??? 在上面的数据中,books变量是由多本书组成,而那些书,有的有一个作者,有的有多个作者,但每个作者都有他自己的地址。 现在,我们想找出作者是"Tom"的书籍的书名。在Java语言中,我们就会有如下形式的代码: ?????? def booksOfTom = [] ?????? ?????? books.each{ ?????????? def book = it ?????????? def aus = it.authors ?????????? ?????????? aus.each{au-> ????????????? if(au.name=='Tom') booksOfTom<<book.name ?????????? } ?????? } ?????? ?????? ??? println booksOfTom ? 但是,上面的需求,在Groovy语言中是如下风格的代码: ?????? def booksOfTom = books.grep{ ?????????? it.authors.any{it.name=='Tom'} ?????? }.name ??? println booksOfTom ? 首先,对"books"使用"grep"方法,最后得到的结果应该是一个"Book"对象的集合,再对该集合取"name",在这里,".name"相当于"*.name"。 在"grep"方法内部,"it.authors"取得了所有的作者,然后再通过"any"方法来遍历作者名为"Tom"的"Book"对象。 这就是结合集合方法和Gpath的Groovy代码风格,开始学起来有一定的难度,但是理解之后,这种代码风格、这种方法十分好用。下面再举一例。 比如,我们想取得作者是"Wallace"的作者所在的城市(这里有重名的作者)。Java语言的编码风格应该是这样的: ?????? def citiesOfWallace = [] ? ?????? books.each{ ?????????? def book = it ?????????? def authors = it.authors ?????????? authors.each{ ????????????? author-> ????????????????? if(author.name == 'Wallace') ????????????????? { ???????????????????? def addr = author.addr ???????????????????? citiesOfWallace << addr.city ????????????????? } ?????????? } ?????? } ? ??? println citiesOfWallace ? 但是Groovy语言却会写出如下风格的代码来: ? ?????? def citiesOfWallace = books.authors.flatten().grep{ ?????????? it.name == 'Wallace' ?????? }.addr.city ?????? ?????? ??? println citiesOfWallace ? "books.authors"的结果是一个集合对象,它里面是由四个集合对象组成,这四个集合对象中的每一个集合对象都是由"Author"对象组成。因此对它们进行"flatten"方法,直接获得一个集合对象,由"Author"对象组成。 然后再进行"Author"对象的"name"属性是否为"Wallace"的匹配,匹配完成,得到一个由"Author"对象组成的集合对象。 最后进行取".addr.city",得到一个由"city"组成的集合。也就是需要的结果。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |