目录

Groovy中自带集合方法

sort方法对集合排序

findAll 查询所有符合条件的元素

collect 返回 一个新的list

inject 强大的累计功能

each、eachWithIndex

find、findIndexOf 查询符合条件的数据

any判断符合条件的数据

every查询所有条件都满足的数据

reverse将集合倒叙返回

first、last、tail查找集合中的元素

通配符 (*.)

GPath对象导航的结构

IO 操作变得更简单

.. 表示 范围

工具

ConfigSlurper配置支持工具

Expando 万能扩展类

属性变化添加监听


上一篇我们从整体学习了Groovy,从整体上了解了Groovy的概念以及特点。并且通过实践学习了Groovy的相关改变,本篇我们一起学习Groovy的开发工具包,通过相关API的学习更加深入的了解Groovy。

Groovy中自带集合方法

Groovy的集合和Java的集合是一样的,不同的是集合方法有差异,我们从集合方法开始学习。

sort方法对集合排序

sort 对集合进行排序,这个方法,可以接收1个闭包作为参数,或者无参数。

// 默认对集合进行正序排序def lst = [13, 12, 15, 14];def newlst = lst.sort();//默认排序println newlst; // 结果[12, 13, 14, 15]// 适用闭包作为参数自定义排序def newlist2 = lst.sort {a, b -> a - b " />findAll 查询所有符合条件的元素 

findAll 返回所有符合条件的元素。它可以接收1个闭包作为参数,或者无参数。

def list = [13, 12, 15, 14,0,-1];//[13, 12, 15, 14, -1]println(list)println(list.findAll())def newlst = list.findAll();//[13, 12, 15, 14, -1]println newlst;// findAll 闭包作为参数返回小于 13 的所有元素def newlst2 = list.findAll {value -> value < 13};println newlst2;// 结果//[12, 0, -1]

collect 返回 一个新的list

collect 返回 一个新的list,它可以接收1个闭包作为参数,或者无参数。

//- collect 返回 一个新的list,它可以接收1个闭包作为参数,或者,无参数,def list = [13, 12, 15, 14, 0, -1];def newlst = [];newlst = list.collect {it * 2}println newlst// 结果// [26, 24, 30, 28, 0, -2]

inject 强大的累计功能

inject函数具备强大的累计功能,类似JS的reduce方法。其中inject的参数可以无,也可以是个闭包。

// 以"I"方法参数设置给sum, 迭代list 将每个元素设置 elem 和 sum 拼接赋值给sumdef list = ["am", "a", "man"]def result = list.inject("I") { sum, elem ->"$sum $elem"}println result//结果:I am a man// 以"2"方法参数设置给p, 迭代 [1, 2, 3] 将每个元素设置 e ,计算 p * e 结果赋值给 pdef intRes = [1, 2, 3].inject(2, {p, e -> p * e;});println(intRes)// 结果:12// 不仅仅可以遍历计算列表,实际的业务场景中,比如计算图书馆的库存。可以看到在计算库存的时候 def totalStore。若采用Java计算的话需要定义中间变量,并且需要写when判断逻辑。class Library {private List bookSeriesList;}class BookSeries {private int suitNum;private List books;}class Book {private String name;private int store;private double price;}def library = new Library(bookSeriesList: [new BookSeries(suitNum: 1, books: [new Book(name: "水浒传(上)", store: 1, price: 100.00),new Book(name: "水浒传(中)", store: 2, price: 120.00),new Book(name: "水浒传(下)", store: 3, price: 150.00),]),new BookSeries(suitNum: 2, books: [new Book(name: "三国演义(上)", store: 4, price: 100.00),new Book(name: "三国演义(中)", store: 5, price: 120.00),new Book(name: "三国演义(下)", store: 6, price: 150.00),]),new BookSeries(suitNum: 3, books: [new Book(name: "西游记(上)", store: 7, price: 100.00),new Book(name: "西游记(中)", store: 8, price: 120.00),new Book(name: "西游记(下)", store: 9, price: 150.00),]),new BookSeries(suitNum: 4, books: [new Book(name: "红楼梦(上)", store: 10, price: 100.00),new Book(name: "红楼梦(中)", store: 11, price: 120.00),new Book(name: "红楼梦(下)", store: 12, price: 150.00),]),new BookSeries(suitNum: 0, books: [new Book(name: "大秦帝国(上)", store: 10, price: 100.00),new Book(name: "大秦帝国(中)", store: 10, price: 120.00),new Book(name: "大秦帝国(下)", store: 10, price: 150.00),]),])when: "统计图书馆丛书总库存"def totalStore = library.bookSeriesList.inject(0) { libraryTotalStore, bookSeries ->libraryTotalStore + (bookSeries.suitNum > 0 ? bookSeries.books.store.sum() * bookSeries.suitNum : 0)}println totalStore

each、eachWithIndex

each普通迭代方法,eachWithIndex用法和each一样,唯一的不同是eachWithIndex的传入的闭包,有两个参数,第一个是值,第二个是索引。

def list = ["a", "b", "c"]list.eachWithIndex {String v, int index ->println v;println index}//结果:a0b1c2

find、findIndexOf 查询符合条件的数据

//- find 返回第一个符合条件的元素,它可以接收1个闭包作为条件参数,或者无参数。// 没有设置参数,默认返回第一个def list = ["a", "b", "c"]def str = list.find();println(str)// 设置闭包参数,默认符合条件的那个str = list.find({e -> e == "b"})println(str)// 设置闭包参数,闭包参数使用默认的关键字 itstr = list.find({it == "b"})println(str)//- findIndexOf 返回指定元素的索引值。它可以接收1个闭包作为条件参数。index = list.findIndexOf({it == "b"})println(index)//结果:abb1

any判断符合条件的数据

//- any 返回boolean值。只要有任意一个符合条件就返回true,它可以接收1个闭包作为条件参数,或者无参数。def list = ["a", "b", "c"]def result = list.any();println(result)result = list.any({it == "e"});println(result)//结果 truefalse

every查询所有条件都满足的数据

//- every 返回boolean值,只有所有符合条件才返回true,它可以接收1个闭包作为条件参数,或者无参数。def list = ["a", "b", "c"]def result = list.every();println(result)result = list.every({it == "a" || it == "b" || it == "c"});println(result)result = list.every({it == "a"});println(result)result = list.every({it == "e"});println(result)// 结果:truetruefalsefalse

reverse将集合倒叙返回

//- reverse, 它将原list倒序,返回新list。无参数def list = ["a", "b", "c"]list = list.reverse();println(list)//结果:[c, b, a]

first、last、tail查找集合中的元素

//- first 返回原list的第一个元素,无参数def list = ["a", "b", "c"]def result = list.first();println(result)//- last 返回原list的最后一个元素,无参数result = list.last();println(result)//- tail 返回一个新list,这个list包含原list(除第一个元素)的所有元素,无参数list = list.tail();println(list)// 结果:ac[b, c]

其它的 groupBy,tokenize, unique,max,min,count,sum 等的函数以后有时间在尝试练习。

通配符 (*.)

在Groovy中我们可以使用通配符(*.)提取我们想要的信息,就想使用Linux命令查询查看某文件类型目录时的通配符一样(ls *.txt)。我们定义一个类,实例化2个Car对象,采用通配符查询每一个实例对象中的make属性。

class Car {String makeString model}def cars = [new Car(make: 'Peugeot', model: '508'),new Car(make: 'Renault', model: 'Clio')]def makes = cars*.makemakes.each {println it}//结果:PeugeotRenault// 创建一个1到10元素的列表,并且每个元素都乘以2def list = (1..10)*.multiply(2)println list// 结果:[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]// 将列表中的所有的字符串转大写def list = ['Denver', 'Cheyenne', 'Reno', 'Sacramento']*.toUpperCase()println(list)// 结果:[DENVER, CHEYENNE, RENO, SACRAMENTO]

GPath对象导航的结构

GPath是groovy代码的一个强劲对象导航的结构,名称的选择与XPath相似,XPath是一个用来描述XML(和等价物)文档的标准。正如XPath,GPath的目标是用在表达试:明确的,紧凑易读的表达式。当染改方式也被封装到Collection的GDK方法中。

// GPath像XPath一样,可以轻松的访问多层的集合对象,如下我们定义一个 List<Map> 类型,快速的获取他的某个健值对。def listOfMaps = [['a': 11, 'b': 12], ['a': 21, 'b': 22], null]println(listOfMaps.a);// [11, 21]// 结果:[11, 21]// 我们看到最后一个元素是 null 无法获取到,但是我们使用通配符就可以listOfMaps = [['a': 11, 'b': 12], ['a': 21, 'b': 22], null]println(listOfMaps*.a)// 结果:[11, 21, null]//采用Collection的GDK方法调用,可以看到是等价于 list*.a 的def list = listOfMaps.collect { it?.a }println(list)// 结果: [11, 21, null]

IO 操作变得更简单

// groovy可以简单明了的进行文件读写操作//* 写入一个文件内容:// 创建文件,并写入new File("book.txt").text = "lly";//* 读取一个文件内容println new File("book.txt").text//* 也可以通过字节方式写入//先手动创建data文件byte[] data = new File("data").bytes;//把data的数据写入book2.txtnew File("book2.txt").bytes = data;//创建 dragons.txt.txt 写入内容后,并读取dragons.txt内容new File('dragons.txt').eachLine { line-> println(line) }//* 如果需要用InputStream,Reader,OutputStream,Writer这些对象进行操作。groovy也提供类似的方法//- 输入流InputStream操作Properties properties = new Properties()File propertiesFile = new File('/Users/liluyang/llyCode/groovy 2/src/main/resources/application.properties')propertiesFile.withInputStream {properties.load(it)}println properties.llyprintln properties.yangzai// 结果:lly曾经的屠龙少年如今变成了恶龙handsomehandsome too//- Reader操作def lineNo = 1def line = 1;new File("dragons.txt").withReader { reader ->while ((line = reader.readLine()) != null) {println "第${lineNo}行内容: ${line}"lineNo++}}// 结果:第1行内容: 曾经的屠龙少年第2行内容: 如今变成了恶龙//- OutputStream操作// 文件复制def srcFile = new File("dragons.txt")def targetFile = new File("book.txt")targetFile.withOutputStream { outputStream ->srcFile.withInputStream { inputStream ->outputStream < writer.writeLine 'Hello World'});//精简版new File('book.txt') << '''Into the ancient pondA frog jumpsWater’s sound!'''//## 极简的URLs操作//1.数据抓取URL url = new URL("https://www.baidu.com/");InputStream input = (InputStream) url.getContent();ByteArrayOutputStream out = new ByteArrayOutputStream();int n = 0;byte[] arr = new byte[1024];while (-1 != (n = input.read(arr)))out.write(arr, 0, n);System.out.println(new String(out.toByteArray()));

.. 表示 范围

在groovy中。范围运算,可以用在循环,switch,字符串截取中。

1..10 - 包含范围的示例

1 .. <10 - 独占范围的示例

'a'..'x' - 范围也可以由字符组成

10..1 - 范围也可以按降序排列

'x'..'a' - 范围也可以由字符组成并按降序排列

// 打印 1 到 10 数字(1..10).each { println(it)}// 打印 1 到 100 数字for (def i in 1..100){println(i)}// 定义字符串,打印[0..4]范围字符串,打印 [0..4, 8..-1] 下标0到下表4的字符串范围,和下标为8到最后的字符串范围def text = 'learning groovy'println text[0..4]println text[0..4, 8..-1]// 结果:learnlearn groovydef list = ['hank', 'john', 'fred']println list[0..1] //[hank, john]// 打印数字 1 到小于 5 的数字(1..<5).each { println(it) }

工具

ConfigSlurper配置支持工具

ConfigSlurper工具用于读取配置文件非常的方便,支持自定义配置文件。我们在Groovy中自定义了一段字符串,按照配置文件的格式读取它。

//- ConfigSlurper工具用于读取配置文件非常的方便def config = new ConfigSlurper().parse(''' app.date = new Date() app.age = 42 app {name = "Test ${this.age}"} ''')def properties = config.toProperties()println(properties."app.date")println(properties."app.age")println(properties."app.name")// 结果:Sun May 28 19:04:39 CST 202342Test 42

Expando 万能扩展类

我之所以这么描述,是这个类台太强大了。Expando类是Groovy语言中的一个相当有趣的类,它的作用类似于GroovyBean类,但比GroovyBean类更加灵活。同时它还更类似于Map类,但也比Map类更加灵活。可以自定义属性和灵活赋值。

//1.def expando = new Expando()expando.name = { -> "abc" }expando.say = { String s -> "${expando.name} says: ${s}" }println expando.say('hello')//2.def person = new Expando()person.name = 'Alice'person.age = 18person.description = {println """ ----------description--------- name: ${delegate.name} age:${delegate.age} ------------------------------ """}person.description()//结果:abc says: hello ----------description--------- name: Alice age:18 ------------------------------

属性变化添加监听

在Groovy中,可以主动监听各种集合对象变化的事件,并作自己的处理。下面以List集合为例,定义监听者ObservableList,并且绑定处理事件函数。就可以在改集合发生变化的时候调用处理函数了。

def list = new ObservableList()def printer = { e -> println e.class }list.addPropertyChangeListener(printer)list.add 'Harry Potter'list.add 'Hermione Granger'list.remove(0)// 结果:class groovy.util.ObservableList$ElementAddedEventclass java.beans.PropertyChangeEventclass groovy.util.ObservableList$ElementAddedEventclass java.beans.PropertyChangeEventclass groovy.util.ObservableList$ElementRemovedEvent