Groovy Series 2 Groovy GDK

        

Table of contents

Collection methods in Groovy

The sort method sorts the collection

findAll Query all eligible elements

collect returns a new list

inject Powerful accumulation function

each、eachWithIndex

find, findIndexOf query qualified data

any judges the data that meets the conditions

every Query data that meets all conditions

reverse returns the collection in reverse

first, last, tail find elements in the collection

wildcard (*.)

Structure of GPath object navigation

IO operations just got easier

.. represents a range

tool

ConfigSlurper configuration support tool

Expando universal extension class

Attribute change add listener


        In the previous article, we learned Groovy as a whole, and understood the concept and characteristics of Groovy as a whole. And through practice, we have learned the relevant changes of Groovy. In this article, we will learn the Groovy development toolkit together, and have a deeper understanding of Groovy through the study of related APIs.

Collection methods in Groovy

        Groovy's collection is the same as Java's collection, the difference is that the collection method is different, we start to learn from the collection method.

The sort method sorts the collection

        sort sorts the collection. This method can receive a closure as a parameter, or no parameter.

// 默认对集合进行正序排序
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 Query all eligible elements

        findAll returns all matching elements. It can receive 1 closure as parameter, or no parameters.

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 returns a new list

        collect returns a new list, which can receive 1 closure as an argument, or no arguments.

//- 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 Powerful accumulation function

        The inject function has a powerful cumulative function, similar to the reduce method of JS. Among them, the parameter of inject can be none, or it can be a closure.

// 以"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

        The ordinary iteration method of each, the usage of eachWithIndex is the same as that of each, the only difference is that the closure passed in by eachWithIndex has two parameters, the first is the value, and the second is the index.

def list = ["a", "b", "c"]

list.eachWithIndex {
    String v, int index ->
        println v;
        println index
}
//结果:
a
0
b
1
c
2

find, findIndexOf query qualified data

//- 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 judges the data that meets the conditions

//- 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 Query data that meets all conditions

//- 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 returns the collection in reverse

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

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

first, last, tail find elements in the collection

//- 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]

        Other functions such as groupBy, tokenize, unique, max, min, count, sum, etc. will have time to try and practice in the future.

wildcard (*.)

        In Groovy, we can use wildcards (*.) to extract the information we want, just like the wildcards (ls *.txt) when using Linux commands to query and view a certain file type directory. We define a class, instantiate two Car objects, and use wildcards to query the make attribute in each instance object.

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]

Structure of GPath object navigation

        GPath is a powerful object navigation structure for groovy code, a name chosen similar to XPath, a standard for describing XML (and equivalent) documents. Like XPath, the goal of GPath is to express: unambiguous, compact and readable expressions. The dyeing method is also encapsulated into the GDK method of Collection.

// 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 operations just got easier

// 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()));

.. represents a range

        in groovy. Range operations can be used in loops, switches, and string interception.

1..10 - Examples of inclusive ranges

1 .. <10 - Example of an exclusive range

'a'..'x' - ranges can also consist of characters

10..1 - Ranges can also be sorted in descending order

'x'..'a' - ranges can also consist of characters and are sorted in descending order

// 打印 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) }

tool

ConfigSlurper configuration support tool

        The ConfigSlurper tool is very convenient for reading configuration files and supports custom configuration files. We have customized a string in Groovy and read it according to the format of the configuration file.

//- 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 universal extension class

        The reason why I describe it this way is that this class is too powerful. The Expando class is a rather interesting class in the Groovy language. Its function is similar to the GroovyBean class, but it is more flexible than the GroovyBean class. At the same time, it is more similar to the Map class, but also more flexible than the Map class. You can customize attributes and assign values ​​flexibly.


//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
               ------------------------------

Attribute change add listener

        In Groovy, you can actively monitor the events of various collection object changes and do your own processing. The following takes the List collection as an example, defines the listener ObservableList, and binds the event processing function. You can call the processing function when the collection changes.

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

Guess you like

Origin blog.csdn.net/lly576403061/article/details/130921886