Gradle 之 Groovy 的进阶
Posted Android实用开发
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Gradle 之 Groovy 的进阶相关的知识,希望对你有一定的参考价值。
好!抖擞精神,此时此刻请允许我吟诗两句:“纸上得来终觉浅,绝知此事要躬行。” 也希望我们以后如果深入理解其中的道理,必须要亲自实践才行。下面进入正题,本文主要介绍 Groovy 中对集合的操作,以及对 xml 和 json 数据格式的解析。
我们都知道在进行数据处理的过程中,对集合的操作是必不可少的。在 Groovy 这种动态语言中,对集合的操作比在 Java 中要简易方便强大的多。上菜品尝一下:
定义一个集合或数组:
//定义一个list集合
def list = new ArrayList() def list = [1,2,3,4,5]
//定义一个数组
def list = [1,2,3,4,5] as int[] int[] list = [1,2,3]
你可能会感觉这个定义和 Java 相比并没有什么优势,是的,请慢慢向下看。我们对数据集合的操作无非是增删改查。接下来看一下如何操作的:
//增加
def listNo = [-1,36,-2,-23,20]
listNo.add(-1)
println(listNo.toListString()) //[-1, 36, 9, -2, -23, 20, -1]
listNo << 2 //在集合里面尾部添加一个数字 2,与 listNo.leftShift(2) 意义相同
println(listNo.toListString())//5 << listNo 语法不对,没有意义和 listNo >> 5 语法不对报错
def integers = listNo + [3, 18]println integers.toListString()// 集合可以直接相加,集合也可以直接加上一个对象
//删除
println(listNo.remove((Object)(-1)))//true删除某个对象,只会删除第一个对象
println(listNo.toListString())//[36, 9, -2, -23, 20, -1]
println listNo -[2,-2] //[9, -23, 20, -1]
println listNo.removeElement(36)//true,删除36这个int对象
//修改
listNo[0] = 2
println(listNo.toListString()) //[2, 9, -2, -23, 20, -1]
上面介绍了增删改,是不是很方便啊?!嗯,不管是不是,看看如何查吧
def listNo = [-1,36,9,-2,-23,20]
println(listNo.find { it -> return it % 2 == 1 })//9
println(listNo.findAll { it -> return it % 2 == 0 }.toListString())//[36, -2, 20]
println(listNo.any {return it % 2 == 1})//true
println(listNo.every{return it % 2 == 1})//false
println(listNo.min()) //-23最小值
println(listNo.max()) //36最大值
println(listNo.count {return it>0}) //3统计list中满足某条件的数量
查数量、查满足条件的一条数据、查满足条件的所有数据,是不是很666。接下来我们来简单看一下集合的排序,Java 中集合的排序借助于 Comparable 或者 Comparator,在 Groovy 中则不需要这样。
//定义一个list集合
def nums = [-9,1,2,-3,4,-5,7]
//=============java中===========
//定义排序规则,按照绝对值从小到大排序
Comparator comparator ={a,b -> a==b ? 0 : Math.abs(a)>Math.abs(b) ? 1 : -1} Collections.sort(nums,comparator)
//从小到大排序
Collections.sort(nums)
//============groovy===================
//从小到大排序
nums.sort()
//定义排序规则,按照绝对值从小到大排序
nums.sort {a,b -> a==b?0:Math.abs(a)>Math.abs(b)? -1 : 1}
println nums
上面介绍了 List 集合的操作,接下来看一下 Map 的定义和相关操作
//定义
// 可以在定义的后面加上比如def map = [name:'Ade','age':18] as HashMap,
// 或者HashMap map = [name:'Ade','age':'18']
def map = [name:'Ade','age':'18']
//map的key可以不带带引号,编译的时候默认加上了''key值不可变
println(map.get('name'))//Ade
println(map['age'])//18
//查找
println map.findAll {it -> it.key}//[name:Ade, age:18]
//增加
map.collage = 'QinHua'
println map.toMapString()//[name:Ade, age:18, collage:QinHua]
map.add = [a:1,b:2]
println map.toMapString()
//map不仅能添加同类型的元素还能添加不同类型的元素
// [name:Ade, age:18, collage:QinHua, add:[a:1, b:2]]
println map.getClass()//c
lass java.util.LinkedHashMap,如果一开始想定义固定的类,
// 此处不能使用.class获取类的类型,因为这个是找map对应key为class的值
在 Map 的遍历中我们常用两个闭包 each 和 eachWithIndex,each 不含角标,eachWithIndex 包含角标参数,例子如下
map.each {def person -> println "The key is ${person.key},The value is ${person.value}"} //The key is name,The value is Ade //The key is age,The value is 18
map.eachWithIndex { Map.Entry<String, String> entry, int i -> println "The position is ${i} ,The key is ${entry.key},The value is ${entry.value}"} //The position is 0 ,The key is name,The value is Ade //The position is 1 ,The key is age,The value is 18//上面的eachWithIndex也可以简写成
//
map.eachWithIndex { def key,value,index-> println "The position is ${index},The key is ${key},The value is ${value}" } //The position is 0,The key is name,The value is Ade //The position is 1,The key is age,The value is 18
有的时候我们需要查找满足条件的数一据,就像List一样查找一部分数据,比如查找一组学生中成绩及格的同学的名称,以及分组操作,Show 代码
def studentMap = [1:[name:'Ade',score:90,sex:'male'],
2:[name:'Lily',score:69,sex:'female'],
3:[name:'Lucy',score:58,sex:'female'],
4:[name:'Ha',score:90,sex:'male']]
def all = studentMap.findAll { def student ->
return student.value.score >= 60
}.collect {
return it.value.name
} println(all.toListString())//[Ade, Lily, Ha]
def groupBy = studentMap.groupBy { def student ->
return student.value.score >= 60 ? '及格' : '不及格'
} println(groupBy.toMapString())
//[及格:[1:[name:Ade, score:90, sex:male], 2:[name:Lily, score:69, sex:female],
// 4:[name:Ha, score:90, sex:male]], 不及格:[3:[name:Lucy, score:58, sex:female]]]
Map 的排序
//排序(按照从大到小排序,a1>a2?-1:1)
def sort = studentMap.sort { def stu1, stu2 -> Number score1 = stu1.value.score Number score2 = stu2.value.score return score1 == score2 ? 0 : score1>score2 ? -1:1} println sort.toMapString()
//[1:[name:Ade, score:90, sex:male], 4:[name:Ha, score:90, sex:male],
// 2:[name:Lily, score:69, sex:female], 3:[name:Lucy, score:58, sex:female]]
接下来补充一个简单的集合------范围
//返回从1开始到10,包含边界
def range = 1..10
println range.contains(10) // true
println range.contains(1) //true
println range.from // 1
println range.to // 10
println range.toListString() // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
//如果要范围从1开始到10,不包含10,则可以如下写
def range1 =1..<10
以上我们了解了基本数据处理和常用集合的使用,接下来了解一下 Groovy 中类的定义和接口的定义。
Groovy 中默认类和方法都是 public 的,并且是实现了 GroovyObject 接口。如果一个类里面重写了 invokeMethod 这个方法, 一个方法找不到的时候就会用此方法来调用来代替你所调用的方法,而不会抛出 MethodMissingException 异常。如果类里面重写了 invokeMethod 和 methodMissing,类找不到的时候会调用 methodMissing 方法
* 注:这些方法的调用都是在运行时调用,编译期间不会判断是否有此方法,而 java 中在编译时期就知道是否有该方法
类的定义
package variable
class Person implements Skill,SecondSkill{
String name
Integer age
//用def来修饰方法 返回值默认是当前类
def increaseAge(Integer years){
this.age += years
}
@Override
void work() {
}
@Override
void eat() {
}
@Override
Object invokeMethod(String s, Object o) {
return "The method is ${s},the params is ${o}"
}
def methodMissing(String s, Object o) {
return "The missmethod is ${s},the params is ${o}"
}
}
接口的定义
package variable
/** * 接口中不允许定义非public修饰的方法,默认都是public的 */
interface Skill {
void work()
}
trait类的定义,类似于接口,不过trait类里面可以有默认的实现,像设计模式中的接口适配模式,定义一个接口里面有很多要实现的方法。然后再定义一个适配器类实现这个接口,里面有一些方法是空实现的,然后再定义一个类来继承这个适配器类,就只需要实现里面的部分方法就可以了
package variable
trait SecondSkill {
abstract void eat()
void play(){
println 'I can play football.'
}
}
类的使用
package variable
//无论是直接类名.还是使用get/set方法都是实质上调用的该对象的get/set方法
def person = new Person(name: 'Ade',age: 27)
println "My name is ${person.name},I'm ${person.age} years old."
person.increaseAge(1)
println "My name is ${person.getName()},I'm ${person.getName()} years old."
请注意!
请注意!
请注意!
Groovy 强大的点来了,Groovy 之类(metaClass相关操作)的属性、方法动态添加,一般注入防范和属性只能在当前类里面进行使用,但是也可以通过 ExpandoMetaClass.enableGlobally() 使得注入的类和属性在全局都可以使用。
用处:比如 java 中引用第三方的包,里面的方法又不全然后只能继承重写里面的方法,但是如果这个类是 final 的话就无法继承重写方法,这中方式就可以处理这个问题。来个例子吧!
Person.metaClass.sex = 'male'
def person = new Person(name: 'Ade',age:18)
println person.sex //male
person.sex = 'female'
println "The new sex is ${person.sex}" //The new sex is female
Person.metaClass.sexUpperCase = {-> sex.toUpperCase()}
println person.sexUpperCase() //FEMALE
//注入一个静态方法
Person.metaClass.static.createPerson = { String name,Integer age ->
new Person(name:name,age: age) }
def person1 = Person.createPerson('Groovy', 10)
println "My name is ${person1.name},I'm ${person1.age} years old."
//My name is Groovy,I'm 10 years old.
全局注入,比如我们对 String 类增加一个全局可用的扩展方法,将字符串转化成逆序大写
class AppManager {
static void init(){ ExpandoMetaClass.enableGlobally() String.metaClass.static.reverseUpperCase = {
value -> value.toString().reverse().toUpperCase() } } } //===========使用============
class MainClass {
static void main(String[] args) { AppManager.init() String s =String.reverseUpperCase('Ade') println s //EDA
} }
小伙伴们,看了这么多累了吧!要不休息一下,来张青春妩媚的图养养眼啊
O(∩_∩)O哈哈~ 是不是一下勾起童年的回忆,来张正常的吧
有木有心动的感觉啊?!心动不如行动,学好技术,迎娶白富美!接下来简单了解一下 Groovy 中对 json、 xml 以及文件的处理。
json 数据的操作之实体对象转换成 json 字符串
def list = [new Person(name: 'Ade',age: 27),new Person(name: 'Vivian',age: 27)]
//def json = toJson(list)
def json = JsonOutput.toJson(list)//与上面一句一样的意思
println(json)
println(JsonOutput.prettyPrint(json))
json 数据的操作之 json 字符串转换成实体对象
def jsonSlurper = new JsonSlurper()
List<Person> parse = jsonSlurper.parseText(json)
println parse.toListString()
在 java 中的 xml 解析一般分为两种,DOM 解析和 SAX 解析,后者相对节省内存,但是还是很麻烦。在 Groovy 中,对 xml 格式的数据进行解析十分方便,举例说明
//''''''用来定义带格式的字符串
def xml =''' <response version="2.0" encoding="UTF-8"> <clazz id='1'> <note> <to id = '1'>Beijing</to> <from>Nanjing</from> <name>Ade</name> <body>Say Hello</body> </note> <note> <to id = '3'>Shanghai</to> <from>Beijing</from> <name>Lily</name> <body>Say Hello to Groovy</body> </note> <note> <to id = '3'>Shanghai</to> <from>Nanjing</from> <name>Vivian</name> <body>Say Hello</body> </note> </clazz> <clazz id='2'> <note> <to id = '3'>Shanghai</to> <from>Hangzhou</from> <name>Ade</name> <body>Say Hangzhou</body> <test> <testName>Test Name</testName> </test> </note> </clazz> </response>''' def xmlSluper = new XmlSlurper() def response = xmlSluper.parseText(xml) println response.clazz[0].note[0].to //Beijing println response.clazz[0].note[0].to.@id //1 def list =[] response.clazz.each{ clazz ->clazz.note.each{ note -> if(note.name == 'Ade'){list.add(note.body)} } } println list.toListString() //[Say Hello, Say Hangzhou] //所谓深度遍历就是跨界层遍历
//def lists = response.clazz.'**'.findAll{// 同样代表深度遍历
def lists = response.clazz.depthFirst().findAll{ test -> return test.testName == 'Test Name' }.collect{ test -> return test.testName }println lists.getClass() //class java.util.ArrayList println lists.toListString() //[Test Name]
//广度遍历,就是遍历同一级别下面的所有,'*'与children()是同一个概念
//def s = response.clazz.'*'.findAll{ def s = response.clazz.children().findAll{ note -> return note.name == 'Vivian' }.collect{ node -> return node.from }
println s.getClass() //class java.util.ArrayList println s.toListString() //[Nanjing]
解析 xml 数据是需要 XmlSlurper 解析类,并调用其parseXXX方法。生成 xml 则需要借助MarkupBuilder 类,例子如下:
def sw = new StringWriter()
def xml = new MarkupBuilder(sw)
xml.clazz(id:'2'){
note(){
to(id:'3','Shanghai')
from('Hangzhou')
name('Ade')
body('Say Hangzhou')
test(){
testName('Test Name')
}
}
}
println sw//生成下面的xml
<clazz id='2'>
<note>
<to id = '3'>Shanghai</to>
<from>Hangzhou</from>
<name>Ade</name>
<body>Say Hangzhou</body>
<test>
<testName>Test Name</testName>
</test>
</note>
</clazz>
上面是生成静态的 xml 数据,那如何动态生成 xml 数据呢?
//动态生成xml
class Clazz{
String id ='2'
def notes = [new Note(to: new To(id: '3',value: 'Shanghai'), from: new From(value: 'Hangzhou'),
name: new Name(value: 'Ade'),
body: new Body(value: 'Say Hangzhou')),
new Note(to: new To(id: '4',value: 'Beijing'),
from: new From(value: 'Nanjing'),
name: new Name(value: 'Ade'),
body: new Body(value: 'Say Beijing'))
]
}
class Note{
To to
From from
Name name
Body body
}
class To{
String id
String value}
class From{
String value
}
class Name{
String value
}
class Body{
String value
}
def sw = new StringWriter()
def xmlBuilder = new MarkupBuilder(sw)
def clazz = new Clazz()
xmlBuilder.clazz(id:clazz.id){
clazz.notes.each {
singleNote -> note(){ //注意此处不能有换行符
to(id:singleNote.to.id,value: singleNote.to.value)+from(value: singleNote.from.value)+name(value: singleNote.name.value) +body(value: singleNote.body.value)
}
}
}
println sw
相信你通过对上面的学习已经了解了对 json 和 xml 数据的解析和操作。接下来看一下对文件的处理,这也是后期 Gradle 打包过程中所用到的基础知识。
def file = new File('../../TestGroovy.iml')
//原文本一行一行输出
file.eachLine { line -> println line }
//原文本输出
def text = file.text //file.getText()
println(text)//获取的数据是整个字符串集合
def lines = file.readLines()
println(lines.toListString())
//读取文件中前10个字符
def reader = file.withReader {reader ->
char[] buffer = new char[10]
reader.read(buffer)
return buffer }
println(reader.getClass())
println(reader)
//直接把文件里面的内容覆盖了
(如果按照下面操作了,可以找历史记录返回正常文件)
def writer=file.withWriter {writer -> writer.write('Ade')
return writer }
println(writer.getClass())
println(writer)
println(copyFile('../../TestGroovy.iml','../../TestGroovy2.iml'))
//拷贝文件
def copyFile(String sourceFile,String targetFile){
try{
def sFile = new File(sourceFile)
if (!sFile.exists()) return def tFile = new File(targetFile)
if (!tFile.exists()){ tFile.createNewFile() } sFile.withReader {reader ->
def lines = reader.readLines() tFile.withWriter {writer -> lines.each { line ->writer.writeLine(line) } } }
return true }catch (Exception e){ e.printStackTrace() }
return false
}
//对象的写读
def person = new Person(name: '大猪蹄子',age: 380) writeObject(person,'../../person.bin')
def object = (Person)readObject('../../person.bin')
println("My name is ${object.name},I'm ${object.age}") //My name is 大猪蹄子,I'm 380
def writeObject(Object o,String path){
try {
def file = new File(path)
if (!file.exists()){
file.createNewFile() }
file.withObjectOutputStream { outPutStream -> outPutStream.writeObject(o) }
return true }catch (Exception e){ e.printStackTrace() }
return false
}
def readObject(String path){
try {
def file = new File(path)
if (!file.exists()){
return null } Object o = file.withObjectInputStream { inputStream-> inputStream.readObject() }
return o }catch (Exception e){ e.printStackTrace() }
return null
}
好,Groovy中基础我们就说的这里了,和Java对比一下:
写法上没有java那么多的限制
比如:;分号的书写,可以写也可以不写;return语句的意义,有事可以不写return。 Groovy相同的功能提供了大量的语法糖实现。在功能上,对java已有的功能进行了很多的扩展
比如json文件和xml文件的解析,文件的处理等等,再比如可以为系统类运行时添加一些方法和属性。Groovy可以编写应用,也可以编写脚本
最后希望本篇大家会喜欢。最后后台回复 “Groovy小资料” 领取小资料一份。
以上是关于Gradle 之 Groovy 的进阶的主要内容,如果未能解决你的问题,请参考以下文章