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"组成的集合。也就是需要的结果。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。