Groovy核心(一):字符串、集合、運算符重載

博客主頁java

Groovy是加強Java平臺的惟一的腳本語言;與Java相比,腳本語言具備更好的表示能力,可以提供更高的抽象等級。
Groovy語言特色:正則表達式

  1. Groovy是一種面向對象的腳本語言,涉及的全部事物都是對象,這一點不像Java語言
  2. Groovy與Java是二進制兼容的,Groovy編譯器產生的字節碼與Java編譯器產生的字節碼是徹底同樣的
  3. Groovy可以徹底使用各類Java API
  4. Groovy是動態類型語言,類型標記存在於對象中,而不是由引用它的變量來決定,因此Groovy不要求聲明變量的類型、方法的參數或者方法的返回值
  5. Groovy語言內置數據結構,如:List對象或者Map對象

學習這門語言,主要是爲了看懂這門腳本語言,知道在Gradle中爲何這麼寫。咱們之後在Gradle中使用Groovy腳本文件,既能夠寫任何符合Groovy語法的代碼,而Groovy又徹底兼容java,意味着能夠在build腳本文件裏寫任何的java代碼,是至關的靈活。segmentfault

基礎語法講解

在Groovy中每個事物最終會被看成某些類的一個實例對象。例如:Groovy中,整數123其實是Integer類的一個實例。Groovy一樣支持運算符重載,也就是 +號能夠出如今 兩個參數之間,例如:123+456 , 可是能夠經過對象調用的方式,123.plus(456)數組

Groovy支持整數和浮點數。注意:整數都是Integer類的實例,浮點數是BigDecimal類的實例。數據結構

def b = 3.14
println b.getClass()

// 打印結果
class java.math.BigDecimal

注意:Groovy中使用關鍵字def 來聲明變量。閉包

關係運算符(< 、> 、 >= 、<=)和等於運算符(== 、 !=)最終都是調用某個方法實現的。關係運算符經過調用compareTo方法實現的,等於運算符經過調用equals方法實現的。函數

// 3 > 5
3.compareTo(5) > 0

def age = 23
def number = 24
// age.equals(number)是經過Integer類的equals方法實現
age == number

字符串講解

在Groovy中,語句後面分號不是必需的,這是Groovy的特性。工具

在Groovy中,可使用單引號(')、雙引號(")或者三引號(''')來封裝字符串。單引號表示純粹的字符串常量,而不能對字符串裏的表達式作運算,可是雙引號能夠。無論哪一種方式表示字符串,它們都是String類型。學習

def age = 23;
println 'my age is ${age}'
println "my age is ${age}"
println '''my age is ${age}'''
println "my age is \${age}"

// 打印結果
my age is ${age}
my age is 23
my age is ${age}
my age is ${age}

從上面的示例能夠看出:單引號中${age}沒有被解釋;若是在美圓符號($)前使用了反斜槓()轉義字符後,也不會被解釋。也就是說,只在字符串須要被解釋的時候使用雙引號,在其餘狀況下字符串使用單引號,單引號沒有運算能力開發工具

咱們能夠經過索引(index)來指定字符串中單個字符或者指定字符集合。通常索引從零開始,該字符串的長度值減一結束。若是負數索引,從字符串的末尾開始往前計算。

def string = "Hello Groovy"
println string[1]  // e
println string[-1]  // y
println string[1..2]  // el    [1..2]表示1到2的範圍
println string[1..<3]  // el
println string[4, 2, 1] // ole

字符串基本操做

def string = "Hello Groovy"
println "Hello" + " Groovy" // Hello Groovy 字符串的合併,至關於"Hello".plus(" Groovy")
println "Hello" * 3   // HelloHelloHello 字符串的賦值
println string - "o Groovy" // Hell 刪除首次出現的字符串
println string.length()   // 12 獲取字符串的長度
println string.size()     // 12 獲取字符串的長度
println string.contains("Groovy")  // true 字符串中是否包含指定的子字符串
println string.count("o")   // 3 統計某個子字符串出現的次數

字符串方法
Groovy開發工具(GDK)擴展了String類的一些方法,如:

方法名稱 函數原型
center String center(Number numberOfChars, CharSequence padding); 返回左右均使用padding填充的新字符串,默認使用空格填充
eachMatch String eachMatch( String regex,Closure closure); 判斷該字符串是否與正則表達式regex匹配。傳遞給閉包的對象是一個匹配成功的字符串數組
leftShift StringBuffer leftShift(Object value); 能夠將多個字符串對象相加,並返回新的字符串。與StringBuffer功能同樣
next String next(); 字符串的末尾字符替換爲末尾字符+1後的字符,並將字符串返回
getAt String getAt(int index); String getAt(IntRange range); String getAt(Collection indices); 根據傳入的索引或者範圍獲取對應的字符
padLeft String padLeft(Number numberOfChars, CharSequence padding); 在字符串的左邊使用padding填充,默認空格填充
padRight String padRight(Number numberOfChars, CharSequence padding); 在字符串的右邊使用padding填充,默認空格填充
plus String plus(CharSequence value); 字符串相加
previous String previous(); 字符串的末尾字符替換爲末尾字符-1後的字符,並將字符串返回
reverse String reverse(); 建立當前字符串的逆序字符串
size int size() 返回字符串的長度
split String[] split(String regex); 與給定正則表達式匹配的規則切割字符串
tokenize List<String> tokenize(CharSequence delimiters); 使用delimiters做爲字符串的分隔符,默認使用空格做爲分隔符

下面示例演示:

def string = "Groovy"
println string.size()  // 6

println string.center(4) // Groovy
println string.center(11, '#')  // ##Groovy###

println string.eachMatch("oo") {
    ch -> print ch  // oo
} // Groovy

println string.getAt(0) // G
println string.getAt(1..3) // roo
println string.getAt([0, 2, 4]) // Gov

println string.leftShift("##") // Groovy##

println string.next() // Groovz
println string.previous() // Groovx

println string.padLeft(8, "#") // ##Groovy
println string.padRight(9, "#") // Groovy###

println string.plus(".") // Groovy.

println string.reverse() // yvoorG

println string.split('oo') // [Gr, vy]

println string.tokenize('r') // [G, oovy]

字符串比較
Groovy中,字符串比較採用詞典順序,大寫字母排在小寫字母前面。若是 str1 與 str2 比較, str1 和 str2 相同,返回0;若是str1 在 str2 前面,返回-1;若是str1在str2後面,返回1

正則表達式
正則表達式是在文本中尋找子字符串的一種模式。
在正則表達式中有兩個特殊的位置標識符,脫字符號^和美圓符號$,分別表示某行的開始與結尾。
正則表達式也包含數量。加符號+ 表示出現一次或者屢次,星號*表示出現零次或者屢次,?表示出現一次或者一次也沒有, {}用來匹配位於{符號以前指定次數的字符, 如:X{n} X剛好出現n次,X{n,} X至少出現n次,X{n,m} X至少出現n次,可是不超過m次

println "aaaaaaab".matches('a*b') // true
println "b".matches('a*b') // true
println "aaaab".matches('a*c?b') // true
println "aaaaab".matches('a{5}b') // true
println "aaab".matches('a{3,}b') // true

在正則表達式中,點符號.表示任意字符,也就是通配符。注意:在正則表達式中須要使用\\\\四個反斜槓表示一個反斜槓。

println '3.14'.matches('3.14') // true
println '3C14'.matches('3.14') // true
println '3.14'.matches('3\\.14') // true
println '3C14'.matches('3\\.14') // false

正則表達式還能夠表示字符類。經過[]元字符表示。如:
[abc] 表示a 、b或c .
[^abc]任何字符,除了 a、b 或 c(否認)
[a-zA-Z] a 到 z 或 A 到 Z,兩頭的字母包括在內(範圍)
\d 數字:[0-9]
\D 非數字: 1
\w 單詞字符:[a-zA-Z_0-9]
\W 非單詞字符:2
XY X 後跟 Y
X|Y X 或 Y
(X) X,做爲捕獲組

println 'ababab'.matches('(ab)*') // true
println 'abababa'.matches('(ab)*') // false
println 'abababa'.matches('(ab)*a') // true
println 'aaac'.matches('([ab])*c') // true
println 'aaac'.matches('(a|b)*c') // true
println 'ababc'.matches('([ab])*c') // true

在Groovy正則表達式中也支持/分隔符模式, 因此不用重複全部的反斜槓符號。

println "\$abc.".matches('\\\$(.*)\\.') // true
// 也能夠下面這張寫法
println "\$abc.".matches(/\$(.*)\./)  // true

列表(List)、映射(Map)、範圍(Range)

這三種數據結構都是引用其餘對象的集合。List和Map可以引用不一樣類型的對象,Range表示整數值的集合。List中每一個對象經過一個整數值索引index獲取,Map可以經過任意類型的值來索引。Groovy徹底兼容了java的集合,而且進行了擴展。

列表(List)

Groovy列表定義方式,下面例子能夠看出:Groovy列表類型使用的就是Java中的ArrayList

// 能夠在Groovy中直接建立ArrayList方式,可是太繁瑣
def list = new ArrayList()
println list.getClass() // class java.util.ArrayList

// Groovy定義方式,是否是很簡單啊
def list2 = [11, 12, 13, 14]
println list2.class // class java.util.ArrayList

// 能夠嵌套不一樣類型元素
def list3 = def list3 = [12, 23, "kerwin", [32, 43]]

Groovy列表經過索引操做符[index]來獲取列表中的元素值,列表的索引index從0開始,指向列表的第一個元素值。索引操做符其實就是List類中定義的getAt方法。負索引表示從右邊開始,-1就是表明從右側數第一個。

def list = [11, 12, 13, 14]
println list[0]  // 訪問第0個元素的值爲11,  list.getAt(0) 
println list[3]  // 訪問第3個元素的值爲14,  list.getAt(3) 
println list[-1]  // 訪問最後一個元素14,  list.getAt(-1)

經過索引index範圍操做列表,包含邊界的索引範圍如:start..end,不包含end邊界的索引範圍如start..<end

def list = [11, 12, 13, 14]
println list[0..2] // [11, 12, 13]
println list[1..<3] // [12, 13]

一樣列表的索引操做符也能夠爲List賦值,也能夠經過putAt方法實現賦值操做.

def list = [11, 12, 13, 14]
list[1] = 22
println list.toListString() // [11, 22, 13, 14]
列表(List)操做

在Groovy中,能夠經過List類提供的方法操做。可是Groovy提供了很是簡單的方法。如集合的迭代操做each方法,該方法接受一個閉包做爲參數,能夠訪問List中的每一個元素

def list = [11, 12, 13, 14]
list.each {
    println "${it}"
}

向列表中添加元素
能夠經過<<運算符(即leftShift)將一個新元素值追加到列表的最後;
一樣可使用+操做符(即plus)追加元素或者鏈接兩個列表,注意:plus(Collection<T> right)方法返回的List是一個新的列表,元素由原始列表中的元素和right中元素組成.

def list = [11, 12, 13, 14]
list.add(15) // [11, 12, 13, 14, 15]
list.leftShift(16) // [11, 12, 13, 14, 15, 16]
list << 17 // [11, 12, 13, 14, 15, 16, 17]
println list.toListString()

// 注意:plus方法返回是一個新的List列表
def plusList = list.plus([18, 19]) // [11, 12, 13, 14, 15, 16, 17, 18, 19]
println plusList.toListString()

def plusList2 = plusList + [20, 21] // [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
println plusList2.toListString()

從列表中刪除元素
調用remove方法刪除元素的時候,咱們須要注意remove(int index)remove(Object o)的區別,第一個是根據索引index刪除列表中的元素,而第二個是根據列表中的元素刪除,因此咱們能夠調用removeAt(int index)removeElement(Object o)來區別

def list = [11, 12, 13, 14]
list.remove(2); // [11, 12, 14]
// 須要注意點
//list.remove(14) // Caught: java.lang.IndexOutOfBoundsException: Index: 14, Size: 3
list.remove((Object)14) // [11, 12]

list.removeAt(1); // [11]
list.removeElement(11) // []

咱們能夠調用removeAll(Closure condition)同時刪除列表中多個元素,參數是閉包,閉包是boolean類型返回值

def list2 = [21, 22, 23, 24]
list2.removeAll {
    return it % 2 == 0
} //

還可使用-操做符(即minus方法)從列表中刪除元素;注意:minus(Collection<?> removeMe)方法返回的List是一個新列表,新列表中的元素由原始列表中的元素移除removeMe中元素組成。

def list3 = [31, 32, 33, 34]
def minusList = list3.minus(32) // [31, 33, 34]
def minusList2 = list3.minus([32, 33]) // [31, 34]
def minusList3 = list3 - [33, 34] // [31, 32]

列表元素排序
在Groovy中排序sort(boolean mutate,Closure closure)方法有多個重載方法,傳入的閉包方式須要有比較的參數並返回0、-一、或者1

def list = [12, -3, 2, 8, -1, 34]

// 第一種方式
Comparator mc = {
    a, b -> a == b ? 0 : Math.abs(a) < Math.abs(b) ? 1 : -1
}
Collections.sort(list, mc) // [34, 12, 8, -3, 2, -1]

// 第二種方式
list.sort {
    a, b -> a == b ? 0 : Math.abs(a) < Math.abs(b) ? -1 : 1
} // [-1, 2, -3, 8, 12, 34]

// boolean mutate 該參數表示是否建立新的列表存放排序後的元素
// false: 建立新的列表存放
def sortList = list.sort(false) {
    a, b -> a == b ? 0 : Math.abs(a) < Math.abs(b) ? 1 : -1
} // [34, 12, 8, -3, 2, -1]

列表中查找元素

def list = [-3, 9, 6, 2, -7, 1, 5]
// 返回查找第一個知足條件的元素,沒有找到返回null
def result = list.find {
    return it % 2 == 0
} // 6

// 返回查找全部知足條件的元素,沒有找到返回空的列表
def resultAll = list.findAll {
    return it % 2 == 0
} // [6, 2]

//列表中只要一個元素知足條件就返回true,不然返回false
def resultAny = list.any {
    return it % 2 == 0
} // true

//列表中全部的元素都知足條件返回true,不然返回false
def resultEvery = list.every {
    return it % 2 == 0
} // false

// 查找列表中最大的值
println list.max {
    return Math.abs(it)
} // 9

// 查找列表最小的值
println list.min() // -7

// 統計列表中知足條件的元素總個數
println list.count {
    return it % 2 == 0
} // 2

映射(Map)

Map用法與List很像。Groovy映射定義方式,從下面例子能夠看出:Groovy列表使用的就是Java中的LinkedHashMap

def colors = [red  : 'ff0000',
              green: '00ff00',
              blue : '0000ff']
println colors.getClass() // java.util.LinkedHashMap
println colors.toMapString() // [red:ff0000, green:00ff00, blue:0000ff]
//注意: 

// 空Map定義方式
def nullMap = [:]
println nullMap.toMapString() // [:]

映射賦值及訪問能夠經過索引的方式,和列表同樣,也能夠經過getAt方法訪問,經過putAt方法賦值。從下面示例可知,Map訪問經過map.key或者map[key]均可以。

def colors = [red  : 'ff0000',
              green: '00ff00',
              blue : '0000ff']
// 訪問
println colors['red'] // ff0000
println colors.blue // 0000ff
println colors['yellow'] // null
println colors.getAt('green') // 00ff00

// 賦值
colors.yellow = 'ffff00'
// 或者  colors['yellow'] = 'ffff00'
// 或者  colors.putAt('yellow', 'ffff00')
println colors.toMapString() // [red:ff0000, green:00ff00, blue:0000ff, yellow:ffff00]

映射(Map)操做

爲了方便操做Map,先定義students 集合數據。

def students = [
        1: [number: '0001', name: 'Bob',
            score : 55, sex: 'male'],
        2: [number: '0002', name: 'Johnny',
            score : 62, sex: 'female'],
        3: [number: '0003', name: 'Claire',
            score : 73, sex: 'female'],
        4: [number: '0004', name: 'Amy',
            score : 66, sex: 'male']
]

Map遍歷, GDK提供了不少each方法。能夠經過Map.Entry、索引index或者key-value方式

// 若是閉包傳入一個參數,是經過Map.Entry遍歷
students.each {
    def student -> println "the kay is ${student.key}, the value is ${student.value}"
}

// 若是閉包傳入2個參數,是經過key-value方式遍歷
students.each {
     key, value -> println "the kay is ${key}, the value is ${value}"
}

// 遍歷的時候,獲取index
students.eachWithIndex{
    def student, int index -> println "index is ${index}, the kay is ${student.key}, the value is ${student.value}"
}
// 遍歷的時候,獲取index
students.eachWithIndex{
    key, value, index -> println "index is ${index}, the kay is ${key}, the value is ${value}"
}

Map查找

// 在Map中查找第一個知足條件,找到返回的是Entry對象,沒有找到返回null
def result = students.find {
    def student -> return student.value.score >= 60
}
println result // 2={number=0002, name=Johnny, score=62, sex=female}

// 在Map中查找全部知足條件的,並將知足條件的數據存放在新的Map中返回
def resultAll = students.findAll {
    key, value -> value.score >= 60
}
//[2:[number:0002, name:Johnny, score:62, sex:female],
// 3:[number:0003, name:Claire, score:73, sex:female],
// 4:[number:0004, name:Amy, score:66, sex:male]]
println resultAll.toMapString()

//查找全部及格的學生姓名
def resultList = students.findAll {
    def student -> student.value.score >= 60
}.collect {
    key, value -> value.name
}
println resultList.toListString() // [Johnny, Claire, Amy]

Map分組

// 按成績及格與不及格分組
def resultGroupMap = students.groupBy {
    def student -> return student.value.score >= 60 ? "及格" : "不及格"
}
// [不及格:[1:[number:0001, name:Bob, score:55, sex:male]],
//  及格:[2:[number:0002, name:Johnny, score:62, sex:female],
//          3:[number:0003, name:Claire, score:73, sex:female],
//          4:[number:0004, name:Amy, score:66, sex:male]]]
println resultGroupMap.toMapString()

Map排序

// 排序
def resultSortMap = students.sort {
    def student1, def student2 ->
        Number score1 = student1.value.score as Number
        Number score2 = student2.value.score as Number
        return score1 == score2 ? 0 : score1 < score2 ? -1 : 1
}
//[1:[number:0001, name:Bob, score:55, sex:male],
// 2:[number:0002, name:Johnny, score:62, sex:female],
// 4:[number:0004, name:Amy, score:66, sex:male],
// 3:[number:0003, name:Claire, score:73, sex:female]]
println resultSortMap.toMapString()

範圍(Range)

範圍包含邊界的範圍經過..表示, 不包含邊界的範圍則在下邊界和上邊界之間使用..<。 範圍能夠經過字符串或者整型值表示.

def range = 1..10
// 獲取當前範圍中元素個數
println range.size() // 10
// 經過索引獲取範圍中元素
println range[2] // 3

// 能夠經過from、to獲取當前範圍的最小元素值、最大元素值
println range.from // 1
println range.to // 10

// 判斷範圍中是否包含給定的元素
println range.contains(4)

//經過字符串表示範圍
def start = 1
def finish = 4
def rangeString = start..finish
println rangeString.getClass() // class groovy.lang.IntRange
println rangeString.toListString() // [1, 2, 3, 4]

若是個人文章對您有幫助,不妨點個贊鼓勵一下(^_^)


  1. 0-9
  2. w
相關文章
相關標籤/搜索