Bootstrap

Groovy语法(三):数据结构

一、列表

•列表的定义

//初始化
def list = [1, 2, 3, 4, 5]

//看起来像是java中的数组,那么groovy中如何定义数组
def array = [1, 2, 3, 4, 5] as int[] //使用as关键字定义一个int数组
int[] array2 = [1, 2, 3, 4, 5] //使用强类型定义一个数组
def array3 = new int[5] //像Java中一样定义

//以此类推,就能定义其他类型的list
def linkList = [1, 2, 3, 4, 5] as LinkedList
println linkList.class //class java.util.LinkedList

•列表的操作(增、删、查、排)
1.list新增

/**
 * list的添加元素
 */
def list = [1, 2, 3, 4, 5]
//以下方法都是在list后面插入一个元素
list.add(6)
println list // [1, 2, 3, 4, 5, 6]
list.leftShift(7)
println list  //[1, 2, 3, 4, 5, 6, 7]
list << 8
println list.toListString() //[1, 2, 3, 4, 5, 6, 7, 8]
def plusList = list + 9
println plusList.toListString() //[1, 2, 3, 4, 5, 6, 7, 8, 9]

2.list删除

/**
 * list的删除操作
 */
def list = [1, 2, 3, 4, 5, 6, 7, 8]
list.remove(7) 
println list  //[1, 2, 3, 4, 5, 6, 7]
list.remove((Object) 7) 
println list  //[1, 2, 3, 4, 5, 6]
list.removeAt(7)  //java.lang.IndexOutOfBoundsException
list.removeElement(6) // [1, 2, 3, 4, 5]
list.removeAll { return it % 2 == 0 } //[1, 3, 5]
println list - [1, 5]  //[3]

3.list排序

/**
 * list的排序
 */
def sortList = [-1, 6, 9, 8, -3, 0, 2]
//java中的排序
//Collections.sort(sortList) //默认由小到大排序
//println sortList  //[-3, -1, 0, 2, 6, 8, 9]
//由大到小排序
//Collections.sort(sortList, new Comparator<Integer>() {
//    @Override
//    int compare(Integer o1, Integer o2) {
//        return o2 - o1
//    }
//})
//println sortList //[9, 8, 6, 2, 0, -1, -3]

//上面的Comparator可以用groovy中的闭包定义(像java8中的lambda表达式)
//def mComparator = { a, b -> a == b ? 0 : Math.abs(a) < Math.abs(b) ? -1 : 1 } //根据绝对值由小到大排序
//Collections.sort(sortList, mComparator)
//println sortList //[0, -1, 2, -3, 6, 8, 9]

//groovy中的DefaultGroovyMethods类提供了这样的排序方法
//sortList.sort()
//println sortList //[-3, -1, 0, 2, 6, 8, 9]
//传入闭包根据自定义的规则排序
//sortList.sort { a, b -> a == b ? 0 : Math.abs(a) < Math.abs(b) ? 1 : -1 } //根据绝对值由大到小排序
//println sortList //[9, 8, 6, -3, 2, -1, 0]

//也可对对象进行排序(根据对象的某些属性去比较)
def sortStringList = ['android', 'groovy', 'java', 'python', 'Hello']
//sortStringList.sort { it -> return it.size() } //根据字符串的长度排序
//println sortStringList //[java, Hello, groovy, python, android]

//查看sort方法的源码,当传入的闭包只有一个参数时,会调用Collections.sort(list, new OrderBy(closure));
//其他时候调用Collections.sort(list, new ClosureComparator(closure));
//那么我们传入的是一个参数的闭包,最终实际比较的就是我们传入的size,然后根据size的比较结果对sortStringList进行排序
/**
 *         int params = closure.getMaximumNumberOfParameters();
 *         if (params == 1) {*         Collections.sort(list, new OrderBy(closure));
 *} else {*             Collections.sort(list, new ClosureComparator(closure));
 *}* **/

//比如我们可以根据首字母排序(忽略大小写)
sortStringList.sort { it[0].toLowerCase() }
println sortStringList //[android, groovy, Hello, java, python]

4.列表的查找,跟闭包与String的结合使用中讲解的类似

/**
 * list的查找
 * */
def findList = [-1, 6, 9, 8, -3, 0, 2]


def result = findList.find { it % 2 == 0 }//查找满足第一个符合条件的元素
println result //6,第一个偶数

def listResult = findList.findAll { it % 2 == 0 } //查找所有符合条件的元素
println listResult //[6, 8, 0, 2]

def anyResult = findList.any { it -> return it % 2 != 0 } //是否有一个满足条件(有一个是奇数)
println anyResult //true

def everyResult = findList.every { it -> return it % 2 != 0 } //是否所有都满足条件
println everyResult //false

println findList.max() // 9 最大值
println findList.min() // -3 最小值

class Student {
    def grade
}
def stu1 = new Student(grade: 85)
def stu2 = new Student(grade: 60)
def stu3 = new Student(grade: 75)
def stu4 = new Student(grade: 100)
def stu5 = new Student(grade: 10)
def stuList = [stu1, stu2, stu3, stu4, stu5]
println stuList.max { it.grade }.grade //100 查找分数最高的学生的分数
println stuList.min { it.grade }.grade //10 查找分数最低的学生的分数

def count = stuList.count { it.grade >= 85 } //统计符合条件的数量
println count //2

//还有其它查找的方法,比如说last(),lastIndexOf()等与java中一致的,就不再重复说明了

二、映射(Map)

Map的定义

def map = new HashMap() //java方式
def colors = [red: 'ff0000', green: '00ff00', blue: '0000ff'] //groovy中,直接以key:value的形式定义,以逗号分隔元素

//获取map中的值
println colors['red'] //ff0000
println colors.getAt('green') //00ff00
println colors.blue //0000ff

Map的操作(增、删、遍历、查、排)
1.Map增添元素

//添加一个元素
//同样有java中的put()方法
colors.yellow = 'ffff00'
println colors.toMapString() //[red:ff0000, green:00ff00, blue:0000ff, yellow:ffff00]

//添加一个集合
def anotherColor = [black: '000000', white: 'ffffff']
colors.complex = anotherColor
println colors.toMapString() //[red:ff0000, green:00ff00, blue:0000ff, yellow:ffff00, complex:[black:000000, white:ffffff]]
//可添加其它类型
def another = [a: 1, b: 2, c: 3]
colors.another = another
println colors.toMapString() //[red:ff0000, green:00ff00, blue:0000ff, yellow:ffff00, complex:[black:000000, white:ffffff], another:[a:1, b:2, c:3]]
println colors.getClass() //class java.util.LinkedHashMap,查看类型需要使用getClass(.class会让编译期以为是要添加一个ket为class的值)

2.Map删除

//与java中的map删除基本一致
colors.remove('complex')
colors.remove('another')
println colors.toMapString() //[red:ff0000, green:00ff00, blue:0000ff, yellow:ffff00]

colors.removeAll {it.value.contains("0000")} //闭包删除
println colors // [green:00ff00, yellow:ffff00]

3.map遍历

def students = [
        1: [number: '0001', name: 'java',
            score : 55, sex: 'male'],
        2: [number: '0002', name: 'android',
            score : 62, sex: 'female'],
        3: [number: '0003', name: 'kotlin',
            score : 73, sex: 'female'],
        4: [number: '0004', name: 'groovy',
            score : 66, sex: 'male']]

//遍历
students.each { def student -> println "the key is ${student.key},the value is ${student.value}" }

//带索引遍历 entry方式
students.eachWithIndex {
    def student, int index -> println "the index is ${index},the key is ${student.key},the value is ${student.value}"
}

//带索引遍历 key-value方式
students.eachWithIndex {
    key, value, index -> println "the index is ${index},the key is ${key},the value is ${value}"
}
/**
 * 带索引输出结果
 */
//the index is 0,the key is 1,the value is [number:0001, name:java, score:55, sex:male]
//the index is 1,the key is 2,the value is [number:0002, name:android, score:62, sex:female]
//the index is 2,the key is 3,the value is [number:0003, name:kotlin, score:73, sex:female]
//the index is 3,the key is 4,the value is [number:0004, name:groovy, score:66, sex:male]

4.Map查找

/**
 * 查找
 */
 
def students = [
        1: [number: '0001', name: 'java',
            score : 55, sex: 'male'],
        2: [number: '0002', name: 'android',
            score : 62, sex: 'female'],
        3: [number: '0003', name: 'kotlin',
            score : 73, sex: 'female'],
        4: [number: '0004', name: 'groovy',
            score : 66, sex: 'male']]

def entry = students.find { def student -> student.value.score >= 60 } //找到第一个及格的学生
println entry // 2={number=0002, name=android, score=62, sex=female}

def entryMap = students.findAll { def student -> student.value.score >= 60 } //找到所有及格的学生
println entryMap //[2:[number:0002, name:android, score:62, sex:female], 3:[number:0003, name:kotlin, score:73, sex:female], 4:[number:0004, name:groovy, score:66, sex:male]]

def count = students.count { def student -> student.value.score >= 60 && student.value.sex == 'female' } //统计所有及格的女学生的数量
println count //2

def nameList = students
        .findAll { def student -> student.value.score >= 60 } //找到所有及格的学生
        .collect { return [name: "${it.value.name}", score: "${it.value.score}"] } //过滤,只要名字和分数 ,collect返回的是一个list
println nameList // [[name:android, score:62], [name:kotlin, score:73], [name:groovy, score:66]]

//分组
def groupMap = students.groupBy { def student -> return student.value.score >= 60 ? '及格' : '不及格' }
println groupMap.toMapString() //[不及格:[1:[number:0001, name:java, score:55, sex:male]], 及格:[2:[number:0002, name:android, score:62, sex:female], 3:[number:0003, name:kotlin, score:73, sex:female], 4:[number:0004, name:groovy, score:66, sex:male]]]

5.Map排序

/**
 * 排序
 */
 
 def students = [
        1: [number: '0001', name: 'java',
            score : 55, sex: 'male'],
        2: [number: '0002', name: 'android',
            score : 62, sex: 'female'],
        3: [number: '0003', name: 'kotlin',
            score : 73, sex: 'female'],
        4: [number: '0004', name: 'groovy',
            score : 66, sex: 'male']]
 
def sortMap = students.sort { student1, student2 ->
    Number score1 = student1.value.score
    Number score2 = student2.value.score
    score1 - score2
} //根据分数由小到大排序

//完整写法
def sortMap2 = students.sort { def student1, def student2 ->
    Number score1 = student1.value.score
    Number score2 = student2.value.score
    return score1 == score2 ? 0 : score1 < score2 ? 1 : -1
} //根据分数由大到小排序

println sortMap //[1:[number:0001, name:java, score:55, sex:male], 2:[number:0002, name:android, score:62, sex:female], 4:[number:0004, name:groovy, score:66, sex:male], 3:[number:0003, name:kotlin, score:73, sex:female]]
println sortMap2 //[3:[number:0003, name:kotlin, score:73, sex:female], 4:[number:0004, name:groovy, score:66, sex:male], 2:[number:0002, name:android, score:62, sex:female], 1:[number:0001, name:java, score:55, sex:male]]

三、范围(Range)

范围的概念:

Range继承了List,是更轻量级的List,当在开发中需要使用类似数字范围的简单的List时,直接使用List相对来说比较重,可使用更加轻量级的Range
范围的使用类型:

范围可以使用满足以下两个条件的任意类型
1.该类型实现了next和previous方法,即重写++和–操作符
2.该类型实现了java.lang.Comparable接口;也就是说实现了compareTo方法,即重写<=>操作符
范围的定义

def range = 1..10
println range[0] //1 获取范围的元素
println range.contains(10) //true 范围是否包含某个元素
println range.from //1 范围的起始值
println range.to // 10 范围的终止值

//在groovy中Date类型也可以定义范围
def today = new Date()
def yesterday = today - 1
def tomorrow = today + 1
def dateRange = yesterday..tomorrow
println dateRange.from //Thu Sep 06 14:24:47 CST 2018
println dateRange[1] //Fri Sep 07 14:24:47 CST 2018
println dateRange.to //Sat Sep 08 14:24:47 CST 2018

def age = [20, 22, 35, 45, 58]
def matchRange = 22..50
println age.grep(matchRange) //[22, 35, 45] 利用grep()获取list中某个范围的值

范围的遍历

/**
 * 遍历
 */
def range = 1..5
range.each { print "$it," } //1,2,3,4,5,

for (i in range) {
    print "$i," //1,2,3,4,5,
}

switch/case中使用范围

static String getGrade(Number number) {
    def result
    switch (number) {
        case 0..<60:
            result = '不及格'
            break
        case 60..<70:
            result = '及格'
            break
        case 70..<85:
            result = '良好'
            break
        case 85..100:
            result = '优秀'
            break
        default:
            result = "分数($number)应该在0..100"
            break
    }
    return result
}

println getGrade(59)//不及格
println getGrade(60)//及格
println getGrade(70) //良好
println getGrade(85) //优秀
println getGrade(101) //分数(101)应该在0..100
;