Groovy學(xué)習(xí)之-Groovy Development Kit(GDK)-集合操作

Groovy學(xué)習(xí)目錄-傳送門

Groovy為各種集合類型提供native支持,包括List吗坚,MapRanges疹吃。 其中大多數(shù)基于Java集合類型,并使用Groovy開發(fā)包中提供的其他方法進(jìn)行了裝飾乓搬。

Lists

List 字面值

您可以按如下所示創(chuàng)建列表思犁。 請注意,[]是空列表表達(dá)式进肯。

def list = [5, 6, 7, 8]
assert list.get(2) == 7
assert list[2] == 7
assert list instanceof java.util.List

def emptyList = []
assert emptyList.size() == 0
emptyList.add(5)
assert emptyList.size() == 1

每個列表表達(dá)式都是創(chuàng)建java.util.List的實(shí)例激蹲。

當(dāng)然,一個list可以用作構(gòu)造另一個list的源:

def list1 = ['a', 'b', 'c']
//構(gòu)造一個新的List江掩,這個List和list1有相同的items
def list2 = new ArrayList<String>(list1)

assert list2 == list1 // == 檢測每一個對應(yīng)的item学辱,判斷它們是否相同

// clone() 也是可以使用的
def list3 = list1.clone()
assert list3 == list1

list是objects的有序集合:

def list = [5, 6, 7, 8]
assert list.size() == 4
assert list.getClass() == ArrayList     //所使用的列表的具體類型

assert list[2] == 7                     // 索引是從0開始的
assert list.getAt(2) == 7               // 同[]運(yùn)算符
assert list.get(2) == 7                 // 替代方法
list[2] = 9
assert list == [5, 6, 9, 8,]           //結(jié)果通過

list.putAt(2, 10)                       //等效于 list[2] = 10
assert list == [5, 6, 10, 8]
assert list.set(2, 11) == 10            // 賦值并返回原值
assert list == [5, 6, 11, 8]

assert ['a', 1, 'a', 'a', 2.5, 2.5f, 2.5d, 'hello', 7g, null, 9 as byte]
//元素可以是不同類型; 允許重復(fù)
assert [1, 2, 3, 4, 5][-1] == 5             // 允許負(fù)數(shù)index乘瓤,從list尾部開始計(jì)數(shù)
assert [1, 2, 3, 4, 5][-2] == 4
assert [1, 2, 3, 4, 5].getAt(-2) == 4       // getAt() 可以使用負(fù)數(shù)index
try {
    [1, 2, 3, 4, 5].get(-2)                 // 但是get()方法不允許使用負(fù)數(shù)index
    assert false
} catch (e) {
    assert e instanceof ArrayIndexOutOfBoundsException
}

List作為布爾表達(dá)式

可以將列表計(jì)算為boolean

// 空list = false
assert ![]

//所有有內(nèi)容的list都 = true
assert [1] && ['a'] && [0] && [0.0] && [false] && [null]

List迭代

迭代列表的元素通常是通過調(diào)用eacheachWithIndex方法,它們對列表的每個項(xiàng)執(zhí)行代碼:

[1, 2, 3].each {
    println "Item: $it"http://it是對應(yīng)于當(dāng)前元素的隱式參數(shù)
}
['a', 'b', 'c'].eachWithIndex { it, i -> //it是當(dāng)前元素, i是索引位置
    println "$i: $it"
}

除了迭代之外策泣,通過將每個元素轉(zhuǎn)換為其他元素來創(chuàng)建新的List通常是很有用的衙傀。 這個操作,通常稱為映射着降,在Groovy中通過collect方法完成:

assert [1, 2, 3].collect { it * 2 } == [2, 4, 6]

//簡潔語法
assert [1, 2, 3]*.multiply(2) == [1, 2, 3].collect { it.multiply(2) }

def list = [0]
//可以給“collect”傳入list參數(shù)差油,收集元素的列表
assert [1, 2, 3].collect(list) { it * 2 } == [0, 2, 4, 6]
assert list == [0, 2, 4, 6]

list操作

過濾和搜索

Groovy開發(fā)工具包包含許多集合的方法,通過這些方法增強(qiáng)標(biāo)準(zhǔn)集合的功能任洞,其中一些如下所示:

assert [1, 2, 3].find { it > 1 } == 2           // 找出第一個符合條件的元素
assert [1, 2, 3].findAll { it > 1 } == [2, 3]   //找出所有符合條件的元素
assert ['a', 'b', 'c', 'd', 'e'].findIndexOf {      // 找出符合條件的第一個元素的index
    it in ['c', 'e', 'g']
} == 2

assert ['a', 'b', 'c', 'd', 'c'].indexOf('c') == 2  // 返回index
assert ['a', 'b', 'c', 'd', 'c'].indexOf('z') == -1 // index返回-1意味著沒有找到結(jié)果
assert ['a', 'b', 'c', 'd', 'c'].lastIndexOf('c') == 4

assert [1, 2, 3].every { it < 5 }               // 如果每一個元素都符合條件則返回true
assert ![1, 2, 3].every { it < 3 }
assert [1, 2, 3].any { it > 2 }                 // 如果有一個元素符合條件就返回true
assert ![1, 2, 3].any { it > 3 }

assert [1, 2, 3, 4, 5, 6].sum() == 21                // 所有元素求和
assert ['a', 'b', 'c', 'd', 'e'].sum {
    it == 'a' ? 1 : it == 'b' ? 2 : it == 'c' ? 3 : it == 'd' ? 4 : it == 'e' ? 5 : 0
    // 求和的時候可以自定義元素的值
} == 15
assert ['a', 'b', 'c', 'd', 'e'].sum { ((char) it) - ((char) 'a') } == 10
assert ['a', 'b', 'c', 'd', 'e'].sum() == 'abcde'
assert [['a', 'b'], ['c', 'd']].sum() == ['a', 'b', 'c', 'd']

// 可以提供初始值
assert [].sum(1000) == 1000
assert [1, 2, 3].sum(1000) == 1006

assert [1, 2, 3].join('-') == '1-2-3'           // 每個元素之間添加字符串
assert [1, 2, 3].inject('counting: ') { str, item -> 
    str + item                     // 減少操作
} == 'counting: 123'
assert [1, 2, 3].inject(0) { count, item ->
    count + item
} == 6

這里是用于在集合中查找最大和最小值的慣用Groovy代碼:

def list = [9, 4, 2, 10, 5]
assert list.max() == 10
assert list.min() == 2

// 單字符的list也可以查找最大值和最小值
assert ['x', 'y', 'a', 'z'].min() == 'a'

// 我們可以用Closure閉包來描述元素的大小
def list2 = ['abc', 'z', 'xyzuvw', 'Hello', '321']
assert list2.max { it.size() } == 'xyzuvw'
assert list2.min { it.size() } == 'z'

除了閉包之外蓄喇,您還可以使用Comparator來定義比較條件:

Comparator mc = { a, b -> a == b ? 0 : (a < b ? -1 : 1) }

def list = [7, 4, 9, -6, -1, 11, 2, 3, -9, 5, -13]
assert list.max(mc) == 11
assert list.min(mc) == -13

Comparator mc2 = { a, b -> a == b ? 0 : (Math.abs(a) < Math.abs(b)) ? -1 : 1 }


assert list.max(mc2) == -13
assert list.min(mc2) == -1

assert list.max { a, b -> a.equals(b) ? 0 : Math.abs(a) < Math.abs(b) ? -1 : 1 } == -13
assert list.min { a, b -> a.equals(b) ? 0 : Math.abs(a) < Math.abs(b) ? -1 : 1 } == -1
添加或刪除元素

我們可以使用[]分配一個新的空List,使用<<為List添加項(xiàng)目:

def list = []
assert list.empty

list << 5
assert list.size() == 1

list << 7 << 'i' << 11
assert list == [5, 7, 'i', 11]

list << ['m', 'o']
assert list == [5, 7, 'i', 11, ['m', 'o']]

//在<<表達(dá)式最前端的list是目標(biāo)list
assert ([1, 2] << 3 << [4, 5] << 6) == [1, 2, 3, [4, 5], 6]

//使用leftShift方法等價于使用 <<
assert ([1, 2, 3] << 4) == ([1, 2, 3].leftShift(4))

我們可以通過多種方式添加到List中:

assert [1, 2] + 3 + [4, 5] + 6 == [1, 2, 3, 4, 5, 6]
// 等價于調(diào)用plus方法
assert [1, 2].plus(3).plus([4, 5]).plus(6) == [1, 2, 3, 4, 5, 6]

def a = [1, 2, 3]
a += 4      //創(chuàng)建了一個新的List
a += [5, 6]
assert a == [1, 2, 3, 4, 5, 6]

assert [1, *[222, 333], 456] == [1, 222, 333, 456]
assert [*[1, 2, 3]] == [1, 2, 3]
assert [1, [2, 3, [4, 5], 6], 7, [8, 9]].flatten() == [1, 2, 3, 4, 5, 6, 7, 8, 9]

def list = [1, 2]
list.add(3)
list.addAll([5, 4])
assert list == [1, 2, 3, 5, 4]

list = [1, 2]
list.add(1, 3) //在索引1前面插入元素3
assert list == [1, 3, 2]

list.addAll(2, [5, 4]) //在索引2前面插入元素[5,4]
assert list == [1, 3, 5, 4, 2]

list = ['a', 'b', 'z', 'e', 'u', 'v', 'g']
list[8] = 'x' // []運(yùn)算符根據(jù)需要使列表增長
// 如果需要插入null
assert list == ['a', 'b', 'z', 'e', 'u', 'v', 'g', null, 'x']

然而交掏,重要的是List上的+運(yùn)算符不會改變List本身妆偏。 與<<相比,+運(yùn)算符會創(chuàng)建一個新的列表盅弛,這通常不是你想要的钱骂,并可能導(dǎo)致性能問題。

Groovy開發(fā)包還包含一些方法挪鹏,使您可以通過元素值輕松地從列表中刪除元素:

assert ['a','b','c','b','b'] - 'c' == ['a','b','b','b']
assert ['a','b','c','b','b'] - 'b' == ['a','c']
assert ['a','b','c','b','b'] - ['b','c'] == ['a']

def list = [1,2,3,4,3,2,1]
list -= 3           //從原始list創(chuàng)建一個新的list见秽,并刪除元素3
assert list == [1,2,4,2,1]
assert ( list -= [2,4] ) == [1,1]

也可以通過引用其索引來刪除元素,在這種情況下讨盒,列表會改變:

def list = [1,2,3,4,5,6,2,2,1]
assert list.remove(2) == 3          //刪除第三個元素并返回第三個元素的值
assert list == [1,2,4,5,6,2,2,1]

如果你只想刪除列表中具有相同值的第一個元素解取,而不是刪除所有元素,則調(diào)用remove方法:

def list= ['a','b','c','b','b']
assert list.remove('c')             // 刪除元素'c'如果刪除成功返回true
assert list.remove('b')             // 刪除第一個找到的元素'b'返顺,如果刪除成功返回true
assert ! list.remove('z')           // 返回false禀苦,因?yàn)闆]有任何元素刪除
assert list == ['a','b','b']

刪除列表中的所有元素可以通過調(diào)用clear方法來完成:

def list= ['a',2,'c',4]
list.clear()
assert list == []
設(shè)置操作

Groovy開發(fā)工具包還包括一些方法,使得它易于推理:

assert 'a' in ['a','b','c']             // 如果元素'a'在list中返回true
assert ['a','b','c'].contains('a')      // 等價于java中的`contains`方法
assert [1,3,4].containsAll([1,4])       // `containsAll` 將檢測每一個待查元素遂鹊,如果都包含在list中振乏,返回true

assert [1,2,3,3,3,3,4,5].count(3) == 4  // 返回元素3在列表中包含的數(shù)量
assert [1,2,3,3,3,3,4,5].count {
    it%2==0                             // 返回符合斷言的元素在列表中包含的數(shù)量
} == 2

assert [1,2,4,6,8,10,12].intersect([1,3,6,9,12]) == [1,6,12]//返回兩個列表的交集

assert [1,2,3].disjoint( [4,6,9] )//兩個列表是互斥的,返回true
assert ![1,2,3].disjoint( [2,4,6] )
排序

使用List經(jīng)常會遇到排序秉扑。 Groovy提供了各種選項(xiàng)來排序List慧邮,從使用閉包到comparators,如下例所示:

assert [6, 3, 9, 2, 7, 1, 5].sort() == [1, 2, 3, 5, 6, 7, 9]

def list = ['abc', 'z', 'xyzuvw', 'Hello', '321']
assert list.sort {
    it.size()
} == ['z', 'abc', '321', 'Hello', 'xyzuvw']

def list2 = [7, 4, -6, -1, 11, 2, 3, -9, 5, -13]
assert list2.sort { a, b -> a == b ? 0 : Math.abs(a) < Math.abs(b) ? -1 : 1 } ==
        [-1, 2, 3, 4, 5, -6, 7, -9, 11, -13]

Comparator mc = { a, b -> a == b ? 0 : Math.abs(a) < Math.abs(b) ? -1 : 1 }

// 僅限于JDK 8+
// list2.sort(mc)
// assert list2 == [-1, 2, 3, 4, 5, -6, 7, -9, 11, -13]

def list3 = [6, -3, 9, 2, -7, 1, 5]

Collections.sort(list3)
assert list3 == [-7, -3, 1, 2, 5, 6, 9]

Collections.sort(list3, mc)
assert list3 == [1, 2, -3, 5, 6, -7, 9]
復(fù)制元素

Groovy開發(fā)工具包還利用了操作符重載舟陆,以提供允許復(fù)制列表元素的方法:

assert [1, 2, 3] * 3 == [1, 2, 3, 1, 2, 3, 1, 2, 3]
assert [1, 2, 3].multiply(2) == [1, 2, 3, 1, 2, 3]
assert Collections.nCopies(3, 'b') == ['b', 'b', 'b']

// 來自JDK的nCopies具有與列表的乘法不同的語義
assert Collections.nCopies(2, [1, 2]) == [[1, 2], [1, 2]] //而不是[1,2,1,2]

Maps

Map 字面值

在Groovy中误澳,可以使用map語法創(chuàng)建map(也稱為關(guān)聯(lián)數(shù)組):[:]

def map = [name: 'Gromit', likes: 'cheese', id: 1234]
assert map.get('name') == 'Gromit'
assert map.get('id') == 1234
assert map['name'] == 'Gromit'
assert map['id'] == 1234
assert map instanceof java.util.Map

def emptyMap = [:]
assert emptyMap.size() == 0
emptyMap.put("foo", 5)
assert emptyMap.size() == 1
assert emptyMap.get("foo") == 5

默認(rèn)情況下,map的key是字符串:[a:1]等價于['a':1]吨娜。 如果您定義一個名為a的變量脓匿,并且您希望a的值為您的map的key淘钟,這可能會令人困惑宦赠。 如果是這種情況陪毡,則必須通過添加括號來轉(zhuǎn)義鍵,如以下示例所示:

def a = 'Bob'
def ages = [a: 43]
assert ages['Bob'] == null // 找不到`Bob`
assert ages['a'] == 43     // 因?yàn)?`a` 是字面值(文本)!

ages = [(a): 43]            // 將`a`用()括起來
assert ages['Bob'] == 43   // 這時就能找到'Bob'的值了

除了map 字面值外, 也可以通過clone方法得到一個map的副本:

def map = [
        simple : 123,
        complex: [a: 1, b: 2]
]
def map2 = map.clone()
assert map2.get('simple') == map.get('simple')
assert map2.get('complex') == map.get('complex')
map2.get('complex').put('c', 3)
assert map.get('complex').get('c') == 3

如前面的示例所示勾扭,生成的map是原始map的淺拷貝

Map屬性符號

Maps也像bean一樣毡琉,所以你可以使用屬性符號在Map中g(shù)et/set項(xiàng),只要鍵是有效的Groovy標(biāo)識符的字符串即可:

def map = [name: 'Gromit', likes: 'cheese', id: 1234]
assert map.name == 'Gromit'     // 同map.get('Gromit')
assert map.id == 1234

def emptyMap = [:]
assert emptyMap.size() == 0
emptyMap.foo = 5
assert emptyMap.size() == 1
assert emptyMap.foo == 5

注意:根據(jù)設(shè)計(jì)妙色,map.foo會一直在map中查找這個key桅滋。這意味著foo.class將在不包含class鍵的map上返回null。如果你是想返回foo的類型身辨,那么你必須使用foo.getClass()方法:

def map = [name: 'Gromit', likes: 'cheese', id: 1234]
assert map.class == null
assert map.get('class') == null
assert map.getClass() == LinkedHashMap // 這很可能是你想要的結(jié)果

map = [1      : 'a',
       (true) : 'p',
       (false): 'q',
       (null) : 'x',
       'null' : 'z']
assert map.containsKey(1) // 數(shù)字1不是一個標(biāo)識符丐谋,所以得這樣調(diào)用
assert map.true == null
assert map.false == null
assert map.get(true) == 'p'
assert map.get(false) == 'q'
assert map.null == 'z'
assert map.get(null) == 'x'

Map迭代

照例,在Groovy開發(fā)工具包中煌珊,Map上的慣用迭代使用eacheachWithIndex方法号俐。 值得注意的是,使用Map字面值符號創(chuàng)建的Map是有序的定庵,也就是說吏饿,如果對Map條目進(jìn)行迭代,將保證條目將按照它們在Map中添加的順序返回蔬浙。

def map = [
        Bob  : 42,
        Alice: 54,
        Max  : 33
]

// `entry` is a map entry
map.each { entry ->
    println "Name: $entry.key Age: $entry.value"
}

// `entry` is a map entry, `i` the index in the map
map.eachWithIndex { entry, i ->
    println "$i - Name: $entry.key Age: $entry.value"
}

// Alternatively you can use key and value directly
map.each { key, value ->
    println "Name: $key Age: $value"
}

// Key, value and i as the index in the map
map.eachWithIndex { key, value, i ->
    println "$i - Name: $key Age: $value"
}

Map操作

添加或刪除元素

向Map中添加元素可以使用put方法猪落,下標(biāo)運(yùn)算符或使用putAll

def defaults = [1: 'a', 2: 'b', 3: 'c', 4: 'd']
def overrides = [2: 'z', 5: 'x', 13: 'x']

def result = new LinkedHashMap(defaults)
result.put(15, 't')
result[17] = 'u'
result.putAll(overrides)
assert result == [1: 'a', 2: 'z', 3: 'c', 4: 'd', 5: 'x', 13: 'x', 15: 't', 17: 'u']

刪除Map的所有元素可以通過調(diào)用clear方法來完成:

def m = [1:'a', 2:'b']
assert m.get(1) == 'a'
m.clear()
assert m == [:]

使用Map字面值語法生成的Map使用object的equalshashcode方法。 這意味著你不應(yīng)該使用哈希碼隨時間變化的object畴博,否則你將無法獲得相關(guān)的值笨忌。

還值得注意的是,您不應(yīng)該使用GString作為Map的鍵绎晃,因?yàn)?code>GString的哈希碼與等效String的哈希碼不同:

def key = 'some key'
def map = [:]
def gstringKey = "${key.toUpperCase()}"
map.put(gstringKey,'value')
assert map.get('SOME KEY') == null
Keys, values and entries

我們可以檢查視圖中的keys, values, and entries:

def map = [1:'a', 2:'b', 3:'c']

def entries = map.entrySet()
entries.each { entry ->
  assert entry.key in [1,2,3]
  assert entry.value in ['a','b','c']
}

def keys = map.keySet()
assert keys == [1,2,3] as Set

由于操作的成功直接取決于正在操作的Map的類型蜜唾,因此視圖(不管是map的entry,key還是value)返回的變化值是非常不鼓勵的庶艾。 特別地袁余,Groovy依賴于來自JDK的集合,通常不能保證集合可以通過keySet咱揍,entrySetvalues安全地操作颖榜。

過濾和搜索

Groovy開發(fā)包包含與List中類似的過濾,搜索和收集方法:

def people = [
    1: [name:'Bob', age: 32, gender: 'M'],
    2: [name:'Johnny', age: 36, gender: 'M'],
    3: [name:'Claire', age: 21, gender: 'F'],
    4: [name:'Amy', age: 54, gender:'F']
]

def bob = people.find { it.value.name == 'Bob' } // 查找單個entry
def females = people.findAll { it.value.gender == 'F' }

//兩個都是返回entries煤裙,但是您可以使用collect來檢索年齡例如
def ageOfBob = bob.value.age
def agesOfFemales = females.collect {
    it.value.age
}

assert ageOfBob == 32
assert agesOfFemales == [21,54]

// 但您也可以使用鍵/對值作為閉包的參數(shù)but you could also use a key/pair value as the parameters of the closures
def agesOfMales = people.findAll { id, person ->
    person.gender == 'M'
}.collect { id, person ->
    person.age
}
assert agesOfMales == [32, 36]

// `every` 如果所有entries都匹配規(guī)則掩完,則返回true
assert people.every { id, person ->
    person.age > 18
}

// `any` 如果任何一個entry匹配規(guī)則,則返回true
assert people.any { id, person ->
    person.age == 54
}
分組

我們可以使用一些標(biāo)準(zhǔn)將List分組到Map中:

assert ['a', 7, 'b', [2, 3]].groupBy {
    it.class
} == [(String)   : ['a', 'b'],
      (Integer)  : [7],
      (ArrayList): [[2, 3]]
]

assert [
        [name: 'Clark', city: 'London'], [name: 'Sharma', city: 'London'],
        [name: 'Maradona', city: 'LA'], [name: 'Zhang', city: 'HK'],
        [name: 'Ali', city: 'HK'], [name: 'Liu', city: 'HK'],
].groupBy { it.city } == [
        London: [[name: 'Clark', city: 'London'],
                 [name: 'Sharma', city: 'London']],
        LA    : [[name: 'Maradona', city: 'LA']],
        HK    : [[name: 'Zhang', city: 'HK'],
                 [name: 'Ali', city: 'HK'],
                 [name: 'Liu', city: 'HK']],
]

Ranges

Ranges允許您創(chuàng)建順序值List硼砰。 這些可以用作List且蓬,因?yàn)?a target="_blank" rel="nofollow">Range擴(kuò)展了java.util.List

使用..符號定義的范圍是包含性的(即List包含from和to值)题翰。

使用.. <符號定義的范圍是半開的恶阴,它們包括第一個值诈胜,但不是最后一個值。

// 全包含的range
def range = 5..8
assert range.size() == 4
assert range.get(2) == 7
assert range[2] == 7
assert range instanceof java.util.List
assert range.contains(5)
assert range.contains(8)

// 半開的range
range = 5..<8
assert range.size() == 3
assert range.get(2) == 7
assert range[2] == 7
assert range instanceof java.util.List
assert range.contains(5)
assert !range.contains(8)

//獲取range的端點(diǎn)而不使用索引
range = 1..10
assert range.from == 1
assert range.to == 10

請注意冯事,int類型的Range實(shí)現(xiàn)了高效率焦匈,創(chuàng)建了一個包含from和to值的輕量級Java對象。

Ranges可以用于實(shí)現(xiàn)java.lang.Comparable以進(jìn)行比較的任何Java對象昵仅,并且還有方法next()previous()返回range中的下一個/上一個項(xiàng)目缓熟。 例如,您可以創(chuàng)建一系列String元素:

// 全包括range
def range = 'a'..'d'
assert range.size() == 4
assert range.get(2) == 'c'
assert range[2] == 'c'
assert range instanceof java.util.List
assert range.contains('a')
assert range.contains('d')
assert !range.contains('e')

您可以使用經(jīng)典的for循環(huán)在一個range上進(jìn)行迭代:

for (i in 1..10) {
    println "Hello ${i}"
}

但是或者摔笤,您可以通過使用each方法迭代Range够滑,在更加Groovy慣用的風(fēng)格中實(shí)現(xiàn)相同的效果:

(1..10).each { i ->
    println "Hello ${i}"
}

Range也可以用在switch語句中:

switch (years) {
    case 1..10: interestRate = 0.076; break;
    case 11..25: interestRate = 0.052; break;
    default: interestRate = 0.037;
}

集合的語法增強(qiáng)

GPath支持

由于對List和Map的屬性符號支持,Groovy提供了語法糖吕世,使得處理嵌套集合變得非常容易版述,如下例所示:

def listOfMaps = [['a': 11, 'b': 12], ['a': 21, 'b': 22]]
assert listOfMaps.a == [11, 21] //GPath 標(biāo)記
assert listOfMaps*.a == [11, 21] //擴(kuò)展點(diǎn)符號

listOfMaps = [['a': 11, 'b': 12], ['a': 21, 'b': 22], null]
assert listOfMaps*.a == [11, 21, null] // 適用于空值
assert listOfMaps*.a == listOfMaps.collect { it?.a } //等價符號
// 但這只會收集非空值
assert listOfMaps.a == [11,21]

擴(kuò)展運(yùn)算符

擴(kuò)展運(yùn)算符可以用于將集合“內(nèi)聯(lián)”到另一個集合中。 它是語法糖寞冯,通常避免調(diào)用putAll并促進(jìn)一行的實(shí)現(xiàn):

assert [ 'z': 900,
         *: ['a': 100, 'b': 200], 'a': 300] == ['a': 300, 'b': 200, 'z': 900]
//在map定義中的擴(kuò)展map符號
assert [*: [3: 3, *: [5: 5]], 7: 7] == [3: 3, 5: 5, 7: 7]

def f = { [1: 'u', 2: 'v', 3: 'w'] }
assert [*: f(), 10: 'zz'] == [1: 'u', 10: 'zz', 2: 'v', 3: 'w']
//函數(shù)參數(shù)中的擴(kuò)展map符號
f = { map -> map.c }
assert f(*: ['a': 10, 'b': 20, 'c': 30], 'e': 50) == 30

f = { m, i, j, k -> [m, i, j, k] }
//使用具有混合未命名和命名參數(shù)的展開map符號
assert f('e': 100, *[4, 5], *: ['a': 10, 'b': 20, 'c': 30], 6) ==
        [["e": 100, "b": 20, "c": 30, "a": 10], 4, 5, 6]

星號“*”運(yùn)算符

“星點(diǎn)”運(yùn)算符是一個快捷運(yùn)算符渴析,允許您對集合的所有元素調(diào)用方法或?qū)傩裕?/p>

assert [1, 3, 5] == ['a', 'few', 'words']*.size()

class Person {
    String name
    int age
}
def persons = [new Person(name:'Hugo', age:17), new Person(name:'Sandra',age:19)]
assert [17, 19] == persons*.age

使用下標(biāo)運(yùn)算符切片

您可以使用下標(biāo)表達(dá)式將其索引到list,數(shù)組和map中吮龄。 有趣的是俭茧,字符串在這種情況下被視為特殊類型的集合:

def text = 'nice cheese gromit!'
def x = text[2]

assert x == 'c'
assert x.class == String

def sub = text[5..10]
assert sub == 'cheese'

def list = [10, 11, 12, 13]
def answer = list[2,3]
assert answer == [12,13]

請注意,您可以使用Range提取集合的一部分:

list = 100..200
sub = list[1, 3, 20..25, 33]
assert sub == [101, 103, 120, 121, 122, 123, 124, 125, 133]

下標(biāo)運(yùn)算符可用于更新現(xiàn)有集合(對于不可變的集合類型):

list = ['a','x','x','d']
list[1..2] = ['b','c']
assert list == ['a','b','c','d']

值得注意的是漓帚,允許使用負(fù)索引母债,從集合的末尾更容易提取:
您可以使用負(fù)指數(shù)從List尝抖,array毡们,String等結(jié)尾計(jì)數(shù)。

text = "nice cheese gromit!"
x = text[-1]
assert x == "!"

def name = text[-7..-2]
assert name == "gromit"

最終昧辽,如果使用向后Range(開始索引大于結(jié)束索引)衙熔,則答案將反過來。

text = "nice cheese gromit!"
name = text[3..1]
assert name == "eci"

增強(qiáng)的集合方法

除了List搅荞,Map或Ranges红氯,Groovy還提供了許多額外的過濾,收集咕痛,分組痢甘,計(jì)數(shù)等方法,這些方法可以直接在集合上使用茉贡,或者更容易迭代塞栅。

特別是,我們邀請您閱讀Groovy開發(fā)包API文檔腔丧,具體來說:

  • 添加到Iterable的方法可以從這里找到
  • 添加到Iterator的方法可以從這里找到
  • 添加到Collection的方法可以從這里找到
  • 添加到List的方法可以從這里找到
  • 添加到Map的方法可以從這里找到

ps: literals這個單詞應(yīng)該翻譯成什么更合適些呢放椰,有朋友知道的話可以留言List literals 我翻譯成了 List字面值 顯然是不對的

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末王暗,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子庄敛,更是在濱河造成了極大的恐慌,老刑警劉巖科汗,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件藻烤,死亡現(xiàn)場離奇詭異,居然都是意外死亡头滔,警方通過查閱死者的電腦和手機(jī)怖亭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來坤检,“玉大人兴猩,你說我怎么就攤上這事≡缧” “怎么了倾芝?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長箭跳。 經(jīng)常有香客問我晨另,道長,這世上最難降的妖魔是什么谱姓? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任借尿,我火速辦了婚禮,結(jié)果婚禮上屉来,老公的妹妹穿的比我還像新娘路翻。我一直安慰自己,他們只是感情好茄靠,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布茂契。 她就那樣靜靜地躺著,像睡著了一般慨绳。 火紅的嫁衣襯著肌膚如雪账嚎。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天儡蔓,我揣著相機(jī)與錄音郭蕉,去河邊找鬼。 笑死喂江,一個胖子當(dāng)著我的面吹牛召锈,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播获询,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼涨岁,長吁一口氣:“原來是場噩夢啊……” “哼拐袜!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起梢薪,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蹬铺,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后秉撇,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體甜攀,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年琐馆,在試婚紗的時候發(fā)現(xiàn)自己被綠了规阀。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡瘦麸,死狀恐怖谁撼,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情滋饲,我是刑警寧澤厉碟,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站屠缭,受9級特大地震影響墨榄,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜勿她,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一袄秩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧逢并,春花似錦之剧、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至玻蝌,卻和暖如春蟹肘,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背俯树。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工帘腹, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人许饿。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓阳欲,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子球化,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理秽晚,服務(wù)發(fā)現(xiàn),斷路器筒愚,智...
    卡卡羅2017閱讀 134,657評論 18 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法赴蝇,類相關(guān)的語法,內(nèi)部類的語法巢掺,繼承相關(guān)的語法句伶,異常的語法,線程的語...
    子非魚_t_閱讀 31,631評論 18 399
  • 前言 人生苦多址遇,快來 Kotlin ,快速學(xué)習(xí)Kotlin斋竞! 什么是Kotlin倔约? Kotlin 是種靜態(tài)類型編程...
    任半生囂狂閱讀 26,209評論 9 118
  • Groovy是一門基于JVM的動態(tài)語言,很多語法和Java類似坝初。大部分Java代碼也同時是合法的Groovy代碼浸剩。...
    樂百川閱讀 3,592評論 0 15
  • 期待遠(yuǎn)方 那里充滿希望 美好總是離得很遠(yuǎn) 眼前茫茫一片 不知還有多久 能夠到達(dá) 匆忙的步伐下 我們信心滿懷 也許荊...
    我是文化人哦閱讀 196評論 0 0