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',authors:[new Author(name:'Tom',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',authors:[new Author(name:'Wallace',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"组成的集合。也就是需要的结果。

没有更多推荐了,返回首页