聲明map
Map的規範和上一篇博客提到的list類似,helist一樣,Map保證可以通過下標來獲取或者設置值,不同的是map可以使用任何類型作爲下標操作符的參數,而list僅僅支持整數,list知道list中元素的順序,而map一般不知道,特殊的map如java.util.TreeMap
也可以知道他們的key的順序。
理論上 ,任何類型都可以作爲map的鍵(key)或者值(value),當使用特殊類型作爲key的時候,需要遵循java.util.Map
在javaDoc中的規定。
通過[:]
來聲明一個空的map,map缺省的類型是java.util.HashMap,也可以通過調用構造方法進行顯示聲明,這樣map仍然可以使用下標操作符進行操作。
def map = [a:1,b:2,c:3]
assert map instanceof HashMap
assert map.size() == 3
assert map['a'] == 1
emptyMap = [:]
assert map.size() == 0
explicitMap = new TreeMap()
explicitMap.putAll(map)
assert explicitMap['a'] == 1
一般情況下key的類型都是字符串,在聲明map的時候可以忽略字符串標記(單引號或者雙引號):assert ["a":1] == [a:1]
,如果key沒有包含特殊字符(需要符合有效表示規則)而且不是groovy的關鍵字,那麼允許通過這種便利的方式進行聲明。
這種方式也有不便的地方,例如,本地變量的內容被用作key。假如有一個本地變量x,它的內容爲’a’,由於[x:1]等價於[‘x’:1],那麼如何保證它等於[‘a’:1]呢?通過把把符號放在圓括號中,強制讓groovy將符號看做一個表達式:
def x = 'a'
assert [x:1] == ['x':1]
assert ['(x)'] == ['x':1]
使用map操作符
Groovy中有三種從map中獲取對象的方法:
- 使用下表操作符,因爲map實現了getAt方法;
- 使用點語法像使用屬性那樣來獲取對象;
- 使用get()方法,可以傳遞一個缺省值,在map中沒有相應的key時,允許返回缺省值,如果沒有缺省值放回null,如果get(key,default)被調用時,key沒有找到,缺省值返回,那麼key:defualt對將被增加到map中。
def map == [a:1,b:2,c:3]
assert map['a'] == 1
assert map.a == 1
assert map.get('a') == 1
assert map.get('a',0) == 1
assert map['d'] == null
assert map.d == null
assert map.get('d') == null
assert map.get('d',0) == 0
assert map.d == 0
map['d'] = 1
assert map.d == 1
map.d = 2
assert map.d == 2
將值分配給map時可以使用下標操作符或者點語法,在使用點語法時,如果key包含了特殊字符,需要使用字符串符號括起來。
map = ["a.b" : 1]
assert map.'a.b' == 1
如果僅僅寫成map.a.b,這裏是不會正常工作的,這其實等價於map.getA().getB().
map方法
map = [a:1,b:2,c:3]
other = [c:3,a:1,b:1]
assert map == other
assert map.isEmpty() == false //是否爲空
assert map.size() == 3
assert map.containKey('a') //判斷map中是否包含給定的key
assert map.containValue(1) //判斷map中是否包含給定的value
//keySet()返回一個key的set集合,不包含重複的key,沒有固定的順序
assert map.keySet() == toSet(['a','b','c'])
assert toSet(map.values()) == toSet([1,2,3])
assert map.entrySet() instanceof Collection
assert map.any{entry -> entry.value > 2} //與list中同名方法類似,
assert map.every{entry -> entry.key < 'd'}
def toSet(list){
new java.util.HashSet(list)
}
遍歷map
//each()
//each()接受兩種形式的閉包:傳遞一個參數,那麼這個參數代表map的一個entry;傳遞兩個參數,那麼就是key和value
def map = [a:1,b:2,c:3]
def store = ''
map.each{entry -> store += entry.key + entry.value}
assert store == "a1b2c3"
def store = ''
map.each{key,value -> store += key store += value}
assert store == "a1b2c3"
修改map
def map = [a:1,b:2,c:3]
map.clear()
assert map.isEmpty()
def map = [a:1,b:2,c:3]
map.remove('a')
assert map.size() == 2
def map = [a:1,b:2,c:3]
assert [a:1,b:2] == map.subMap(['a','b'])
assert [a:1,b:2] == map.findAll{entry -> entry.value < 3}
neWMap = map.find{entry -> entry.value < 3} //返回符合條件一個entry
//collect() 返回閉包結果組成的list(是否返回可選)
assert [2,4,6] == map.collect{entry -> entry.value*= 2}
//collect()可以接受一個list
assert [1,2,2,4,6] == map.collect([1,2]){entry -> entry.value*= 2}
map實戰
統計文章中單詞出現的頻率
def text =
"""
When I say I believe all children can learn, people sometimes misunderstand.
Because I have been working with poor, minority children in Harlem for the last 25 years,
some people think I am talking about good kids in bad environments — that if you give a bright kid from a poor family a good educational support system,
he or she can succeed. That's absolutely true, but that's not what I mean
"""
def works = text.tokenize()
def wordFrequency = [:]
words.each{work ->
wordFrequency[work] = wordFrequency.get(work,0) + 1
}
def workList = wordFrequency.keySet().toList()
workList.sort{wordFrequency[it]}
def statistic = "\n"
workList[-1..-6].each{work ->
statistic += work.padLeft(12) + ":"
statistic += wordFrequency[work] + "\n"
}
assert statistic ==
"""
I:5
a:3
good:2
in:2
people:2
can:2
"""