Groovy系列二 Groovy GDK

超、凢脫俗 2024-03-16 10:20 113阅读 0赞

目录

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。

67507a473cc540c6bdb07632a0209fe8.png

Groovy中自带集合方法

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

sort方法对集合排序

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

  1. // 默认对集合进行正序排序
  2. def lst = [13, 12, 15, 14];
  3. def newlst = lst.sort();//默认排序
  4. println newlst;
  5. // 结果
  6. [12, 13, 14, 15]
  7. // 适用闭包作为参数自定义排序
  8. def newlist2 = lst.sort {
  9. a, b -> a - b ? -1 : 1
  10. }
  11. println newlist2;
  12. // 结果
  13. [15, 14, 13, 12]

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

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

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

collect 返回 一个新的list

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

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

inject 强大的累计功能

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

  1. // 以"I"方法参数设置给sum, 迭代list 将每个元素设置 elem 和 sum 拼接赋值给sum
  2. def list = ["am", "a", "man"]
  3. def result = list.inject("I") { sum, elem ->
  4. "$sum $elem"
  5. }
  6. println result
  7. //结果:I am a man
  8. // 以"2"方法参数设置给p, 迭代 [1, 2, 3] 将每个元素设置 e ,计算 p * e 结果赋值给 p
  9. def intRes = [1, 2, 3].inject(2, {
  10. p, e -> p * e;
  11. });
  12. println(intRes)
  13. // 结果:12
  14. // 不仅仅可以遍历计算列表,实际的业务场景中,比如计算图书馆的库存。可以看到在计算库存的时候 def totalStore。若采用Java计算的话需要定义中间变量,并且需要写when判断逻辑。
  15. class Library {
  16. private List<BookSeries> bookSeriesList;
  17. }
  18. class BookSeries {
  19. private int suitNum;
  20. private List<Book> books;
  21. }
  22. class Book {
  23. private String name;
  24. private int store;
  25. private double price;
  26. }
  27. def library = new Library(
  28. bookSeriesList: [
  29. new BookSeries(suitNum: 1, books: [
  30. new Book(name: "水浒传(上)", store: 1, price: 100.00),
  31. new Book(name: "水浒传(中)", store: 2, price: 120.00),
  32. new Book(name: "水浒传(下)", store: 3, price: 150.00),
  33. ]),
  34. new BookSeries(suitNum: 2, books: [
  35. new Book(name: "三国演义(上)", store: 4, price: 100.00),
  36. new Book(name: "三国演义(中)", store: 5, price: 120.00),
  37. new Book(name: "三国演义(下)", store: 6, price: 150.00),
  38. ]),
  39. new BookSeries(suitNum: 3, books: [
  40. new Book(name: "西游记(上)", store: 7, price: 100.00),
  41. new Book(name: "西游记(中)", store: 8, price: 120.00),
  42. new Book(name: "西游记(下)", store: 9, price: 150.00),
  43. ]),
  44. new BookSeries(suitNum: 4, books: [
  45. new Book(name: "红楼梦(上)", store: 10, price: 100.00),
  46. new Book(name: "红楼梦(中)", store: 11, price: 120.00),
  47. new Book(name: "红楼梦(下)", store: 12, price: 150.00),
  48. ]),
  49. new BookSeries(suitNum: 0, books: [
  50. new Book(name: "大秦帝国(上)", store: 10, price: 100.00),
  51. new Book(name: "大秦帝国(中)", store: 10, price: 120.00),
  52. new Book(name: "大秦帝国(下)", store: 10, price: 150.00),
  53. ]),
  54. ]
  55. )
  56. when: "统计图书馆丛书总库存"
  57. def totalStore = library.bookSeriesList.inject(0) { libraryTotalStore, bookSeries ->
  58. libraryTotalStore + (bookSeries.suitNum > 0 ? bookSeries.books.store.sum() * bookSeries.suitNum : 0)
  59. }
  60. println totalStore

each、eachWithIndex

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

  1. def list = ["a", "b", "c"]
  2. list.eachWithIndex {
  3. String v, int index ->
  4. println v;
  5. println index
  6. }
  7. //结果:
  8. a
  9. 0
  10. b
  11. 1
  12. c
  13. 2

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

  1. //- find 返回第一个符合条件的元素,它可以接收1个闭包作为条件参数,或者无参数。
  2. // 没有设置参数,默认返回第一个
  3. def list = ["a", "b", "c"]
  4. def str = list.find();
  5. println(str)
  6. // 设置闭包参数,默认符合条件的那个
  7. str = list.find({e -> e == "b"})
  8. println(str)
  9. // 设置闭包参数,闭包参数使用默认的关键字 it
  10. str = list.find({it == "b"})
  11. println(str)
  12. //- findIndexOf 返回指定元素的索引值。它可以接收1个闭包作为条件参数。
  13. index = list.findIndexOf({it == "b"})
  14. println(index)
  15. //结果:
  16. a
  17. b
  18. b
  19. 1

any判断符合条件的数据

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

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

  1. //- every 返回boolean值,只有所有符合条件才返回true,它可以接收1个闭包作为条件参数,或者无参数。
  2. def list = ["a", "b", "c"]
  3. def result = list.every();
  4. println(result)
  5. result = list.every({it == "a" || it == "b" || it == "c"});
  6. println(result)
  7. result = list.every({it == "a"});
  8. println(result)
  9. result = list.every({it == "e"});
  10. println(result)
  11. // 结果:
  12. true
  13. true
  14. false
  15. false

reverse将集合倒叙返回

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

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

  1. //- first 返回原list的第一个元素,无参数
  2. def list = ["a", "b", "c"]
  3. def result = list.first();
  4. println(result)
  5. //- last 返回原list的最后一个元素,无参数
  6. result = list.last();
  7. println(result)
  8. //- tail 返回一个新list,这个list包含原list(除第一个元素)的所有元素,无参数
  9. list = list.tail();
  10. println(list)
  11. // 结果:
  12. a
  13. c
  14. [b, c]

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

通配符 (*.)

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

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

GPath对象导航的结构

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

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

IO 操作变得更简单

  1. // groovy可以简单明了的进行文件读写操作
  2. //* 写入一个文件内容:
  3. // 创建文件,并写入
  4. new File("book.txt").text = "lly";
  5. //* 读取一个文件内容
  6. println new File("book.txt").text
  7. //* 也可以通过字节方式写入
  8. //先手动创建data文件
  9. byte[] data = new File("data").bytes;
  10. //把data的数据写入book2.txt
  11. new File("book2.txt").bytes = data;
  12. //创建 dragons.txt.txt 写入内容后,并读取dragons.txt内容
  13. new File('dragons.txt').eachLine { line-> println(line) }
  14. //* 如果需要用InputStream,Reader,OutputStream,Writer这些对象进行操作。groovy也提供类似的方法
  15. //- 输入流InputStream操作
  16. Properties properties = new Properties()
  17. File propertiesFile = new File('/Users/liluyang/llyCode/groovy 2/src/main/resources/application.properties')
  18. propertiesFile.withInputStream {
  19. properties.load(it)
  20. }
  21. println properties.lly
  22. println properties.yangzai
  23. // 结果:
  24. lly
  25. 曾经的屠龙少年
  26. 如今变成了恶龙
  27. handsome
  28. handsome too
  29. //- Reader操作
  30. def lineNo = 1
  31. def line = 1;
  32. new File("dragons.txt").withReader { reader ->
  33. while ((line = reader.readLine()) != null) {
  34. println "第${lineNo}行内容: ${line}"
  35. lineNo++
  36. }
  37. }
  38. // 结果:
  39. 1行内容: 曾经的屠龙少年
  40. 2行内容: 如今变成了恶龙
  41. //- OutputStream操作
  42. // 文件复制
  43. def srcFile = new File("dragons.txt")
  44. def targetFile = new File("book.txt")
  45. targetFile.withOutputStream { outputStream ->
  46. srcFile.withInputStream { inputStream ->
  47. outputStream << inputStream
  48. }
  49. }
  50. //- 写入Writer操作
  51. //写入
  52. new File('book.txt').withWriter('utf-8', {
  53. writer -> writer.writeLine 'Hello World'
  54. });
  55. //精简版
  56. new File('book.txt') << '''Into the ancient pond
  57. A frog jumps
  58. Water’s sound!'''
  59. //## 极简的URLs操作
  60. //1.数据抓取
  61. URL url = new URL("https://www.baidu.com/");
  62. InputStream input = (InputStream) url.getContent();
  63. ByteArrayOutputStream out = new ByteArrayOutputStream();
  64. int n = 0;
  65. byte[] arr = new byte[1024];
  66. while (-1 != (n = input.read(arr)))
  67. out.write(arr, 0, n);
  68. System.out.println(new String(out.toByteArray()));

.. 表示 范围

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

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

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

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

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

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

  1. // 打印 1 到 10 数字
  2. (1..10).each { println(it)}
  3. // 打印 1 到 100 数字
  4. for (def i in 1..100){
  5. println(i)
  6. }
  7. // 定义字符串,打印[0..4]范围字符串,打印 [0..4, 8..-1] 下标0到下表4的字符串范围,和下标为8到最后的字符串范围
  8. def text = 'learning groovy'
  9. println text[0..4]
  10. println text[0..4, 8..-1]
  11. // 结果:
  12. learn
  13. learn groovy
  14. def list = ['hank', 'john', 'fred']
  15. println list[0..1] //[hank, john]
  16. // 打印数字 1 到小于 5 的数字
  17. (1..<5).each { println(it) }

工具

ConfigSlurper配置支持工具

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

  1. //- ConfigSlurper工具用于读取配置文件非常的方便
  2. def config = new ConfigSlurper().parse('''
  3. app.date = new Date()
  4. app.age = 42
  5. app {
  6. name = "Test ${this.age}"
  7. }
  8. ''')
  9. def properties = config.toProperties()
  10. println(properties."app.date")
  11. println(properties."app.age")
  12. println(properties."app.name")
  13. // 结果:
  14. Sun May 28 19:04:39 CST 2023
  15. 42
  16. Test 42

Expando 万能扩展类

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

  1. //1.
  2. def expando = new Expando()
  3. expando.name = { -> "abc" }
  4. expando.say = { String s -> "${expando.name} says: ${s}" }
  5. println expando.say('hello')
  6. //2.
  7. def person = new Expando()
  8. person.name = 'Alice'
  9. person.age = 18
  10. person.description = {
  11. println """
  12. ----------description---------
  13. name: ${delegate.name}
  14. age: ${delegate.age}
  15. ------------------------------
  16. """
  17. }
  18. person.description()
  19. //结果:
  20. abc says: hello
  21. ----------description---------
  22. name: Alice
  23. age: 18
  24. ------------------------------

属性变化添加监听

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

  1. def list = new ObservableList()
  2. def printer = { e -> println e.class }
  3. list.addPropertyChangeListener(printer)
  4. list.add 'Harry Potter'
  5. list.add 'Hermione Granger'
  6. list.remove(0)
  7. // 结果:
  8. class groovy.util.ObservableList$ElementAddedEvent
  9. class java.beans.PropertyChangeEvent
  10. class groovy.util.ObservableList$ElementAddedEvent
  11. class java.beans.PropertyChangeEvent
  12. class groovy.util.ObservableList$ElementRemovedEvent

发表评论

表情:
评论列表 (有 0 条评论,113人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Groovy

    Groovy 是 用于Java [虚拟机][Link 1]的一种敏捷的 [动态语言][Link 2],它是一种成熟的 [面向对象][Link 3]编程语言,既可以用于面向对象编

    相关 Groovy入门

    目录 一. Groovy是啥? 二. 配置Groovy 三. 体验Groovy自带的编辑器 四. 使用Intellij IDEA创建Groovy工程 五. Groov

    相关 Groovy快速入门-1-Groovy简介

           补上一个系列,叫Groovy快速入门,如果你学习过Java并且有一定的水平,其实Groovy项目中,你完全可以百分百Java代码实现,这没有毛病,如果你学习的是P