Groovy系列二 Groovy GDK

        

目录

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 ? -1 : 1
}
println newlist2; 
//  结果
[15, 14, 13, 12]

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 拼接赋值给sum
def 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 结果赋值给 p
def intRes = [1, 2, 3].inject(2, {
    p, e -> p * e;
});
println(intRes)
// 结果:12

// 不仅仅可以遍历计算列表,实际的业务场景中,比如计算图书馆的库存。可以看到在计算库存的时候 def totalStore。若采用Java计算的话需要定义中间变量,并且需要写when判断逻辑。
class Library {
    private List<BookSeries> bookSeriesList;
}

class BookSeries {
    private int suitNum;
    private List<Book> 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
}
//结果:
a
0
b
1
c
2

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

//- find 返回第一个符合条件的元素,它可以接收1个闭包作为条件参数,或者无参数。
// 没有设置参数,默认返回第一个
def list = ["a", "b", "c"]
def str = list.find();
println(str)

// 设置闭包参数,默认符合条件的那个
str = list.find({e -> e == "b"})
println(str)
// 设置闭包参数,闭包参数使用默认的关键字 it
str = list.find({it == "b"})
println(str)

//- findIndexOf 返回指定元素的索引值。它可以接收1个闭包作为条件参数。
index = list.findIndexOf({it == "b"})
println(index)

//结果:
a
b
b
1

any判断符合条件的数据

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

//结果 
true
false

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)

// 结果:
true
true
false
false

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)

// 结果:
a
c
[b, c]

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

通配符 (*.)

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

class Car {
    String make
    String model
}
def cars = [
        new Car(make: 'Peugeot', model: '508'),
        new Car(make: 'Renault', model: 'Clio')]
def makes = cars*.make

makes.each {
    println it
}

//结果:
Peugeot
Renault

// 创建一个1到10元素的列表,并且每个元素都乘以2
def 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<String, Integer>> 类型,快速的获取他的某个健值对。
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.txt
new 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.lly
println properties.yangzai

// 结果:
lly
曾经的屠龙少年
如今变成了恶龙
handsome
handsome too

//- Reader操作
def lineNo = 1
def 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 << inputStream
    }
}

//- 写入Writer操作
//写入
new File('book.txt').withWriter('utf-8', {
    writer -> writer.writeLine 'Hello World'
});

//精简版
new File('book.txt') << '''Into the ancient pond
    A frog jumps
    Water’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]

// 结果:
learn
learn groovy

def 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 2023
42
Test 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 = 18

person.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$ElementAddedEvent
class java.beans.PropertyChangeEvent
class groovy.util.ObservableList$ElementAddedEvent
class java.beans.PropertyChangeEvent
class groovy.util.ObservableList$ElementRemovedEvent

猜你喜欢

转载自blog.csdn.net/lly576403061/article/details/130921886