Groovy のマップの使い方

  1. 初期化
  2. 追加系
      1. putAll メソッド
  3. 取得系
    1. 最大要素取得
      1. Entry max(Closure closure)
    2. 最小要素取得
      1. Entry min(Closure closure)
    3. 条件に一致する最初の要素を取得
      1. Object find(Closure closure)
    4. 条件に一致する要素を全部取得
      1. Map findAll(Closure closure)
      2. Map drop(int num) メソッド
      3. Map dropWhile(Closure closure) メソッド
      4. Map take(int num) メソッド
      5. Map takeWhile(Closure closure) メソッド
    5. ソートしたマップを作成
      1. Collection sort() メソッド
      2. Collection sort(Closure closure)
      3. Collection sort(Comparator comparator)
      4. Collection toSorted()
      5. Collection toSorted(Closure closure)
      6. Collection toSorted(Comparator comparator)
  4. 更新系
  5. 削除系
      1. Object remove(Object key) メソッド
    1. 全削除
      1. void clear() メソッド
  6. ループ系
    1. each【非破壊】
    2. eachWithIndex メソッド
    3. reverseEach メソッド
  7. 真偽判定系
    1. 真偽判定
    2. 条件に一致する要素が存在するか
      1. boolean any(Closure closure) 【非破壊】
    3. 全要素が条件に一致するか
      1. boolean every(Closure closure) 【非破壊】
  8. 集合処理系
    1. 和集合
      1. + オペレータ、Map plus(Map right) メソッド【非破壊】
      2. Map putAll(Collection entries)メソッド【破壊】
    2. 差集合
      1. - オペレータ、Map minus(Map removeMe) メソッド【非破壊】
    3. 積集合
      1. Map intersect(Map right) メソッド【非破壊】
  9. collect
    1. List collect(Closure transform)
    2. *. オペレータ
    3. Collection collect(Collection collector, Closure transform)
  10. collectEntries
    1. Map collectEntries(Closure transform) メソッド
    2. Map collectEntries(Map collector, Closure transform) メソッド
  11. グループ化
    1. Map groupBy(Closure closure)
    2. Map groupBy(Object closures)
    3. Map groupBy(List closures)
  12. inject
    1. Object inject(Object initalValue, Closure closure)
  13. その他のオペレータ系
    1. *:オペレータ
  14. その他

初期化

def map = [:]
assert map == [:]
assert map instanceof LinkedHashMap

map = ['a': 'A', 'b': 'B']
assert map['a'] == 'A'

assert map['a'] == 'A'
assert map['b'] == 'B'

LinkedHashMap のため、キーは挿入順に格納される。

def map = ['a': 'A', 'b': 'B', 'c', 'C']
assert map*.key == ['a', 'b', 'c']

初期化時のキーはデフォルトで文字として扱われる。

def map = [a: 'A', b: 'B']
assert map == ['a': 'A', 'b': 'B']

変数をキーにする場合は、キーの変数名を()で囲む

def key1 = 'a'
def key2 = 'b'
def map = [(key1): 'A', (key2): 'B']
assert map == ['a': 'A', 'b': 'B']

追加系

def map = [a: 'A']
map.put('b', 'B')
assert map == [a: 'A', b: 'B']

map['c'] = 'C'
assert map == [a: 'A', b: 'B', c: 'C']

map.leftShift([d: 'D'])
assert map == [a: 'A', b: 'B', c: 'C', d: 'D']

map << [e: 'E']
assert map == [a: 'A', b: 'B', c: 'C', d: 'D', e: 'E']

map.leftShift([f: 'F', g: 'G'])
assert map == [a: 'A', b: 'B', c: 'C', d: 'D', e: 'E', f: 'F', g: 'G']

map << [h: 'H', i: 'I']
assert map == [a: 'A', b: 'B', c: 'C', d: 'D', e: 'E', f: 'F', g: 'G', h: 'H', i: 'I']

map.putAll([b: 'J', k: 'K'])
assert map == [a: 'A', b: 'J', c: 'C', d: 'D', e: 'E', f: 'F', g: 'G', h: 'H', i: 'I', k: 'K']

GString をキーにする場合は注意

def key1 = "${'A'.toLowerCase()}"
def key2 = "${'B'.toLowerCase()}"
def key3 = "${'C'.toLowerCase()}"

// 初期化時に使用した場合、期待通りに動かない
def map = [(key1): 'A']
assert map['a'] != 'A'
assert map[key1] != 'A'
// キーは GString
assert map.find { it.key == 'a' }.key instanceof GString

// put (JDK) を使用した場合、期待通りに動かない
map.put(key2, 'B')
assert map['b'] != 'B'
assert map[key2] != 'B'
// キーは GString
assert map.find { it.key == 'b' }.key instanceof GString

// putAt (GDK) を使用した場合、期待通りに動く
map[key3] = 'C'
assert map['c'] == 'C'
assert map[key3] == 'C'
// キーは String
assert map.find { it.key == 'c' }.key instanceof String

putAll メソッド

def map = [a: 'A', b: 'B', c: 'C']
map.putAll([d: 'D', e: 'E'])
assert map == [a: 'A', b: 'B', c: 'C', d: 'D', e: 'E']

キーが重複する場合は、上書きされる。

def map = [a: 'A', b: 'B', c: 'C']
map.putAll([a: 'a', d: 'D'])
assert map == [a: 'a', b: 'B', c: 'C', d: 'D']

取得系

def map = [a: 'A', b: 'B']
assert map.get('a') == 'A'
assert map.getAt('a') == 'A'
assert map['a'] == 'A'
assert map.'a' == 'A'
assert map.a == 'A'

class を取得したい場合

def map = [:]
assert map.class == map['class'] && map.class == null
assert map.getClass() == LinkedHashMap

最大要素取得

Entry max(Closure closure)

def map = [a: 'A', b: 'B', c: 'C']
def max = map.max { it.key }
assert max.key == 'c' && max.value == 'C'

max = map.max { a, b -> a.key <=> b.key }
assert max.key == 'c' && max.value == 'C'

最小要素取得

Entry min(Closure closure)

def map = [a: 'A', b: 'B', c: 'C']
def min = map.min { it.key }
assert min.key == 'a' && min.value == 'A'

min = map.min { a, b -> a.key <=> b.key }
assert min.key == 'a' && min.value == 'A'

条件に一致する最初の要素を取得

Object find(Closure closure)

def map = [a: 1, b: 3]
assert map.find { entry -> entry.value == 3 }.key == 'b'
assert map.find { key, value -> value == 3 }.key == 'b'

条件に一致する要素を全部取得

Map findAll(Closure closure)

【重要】 findAll()の方は List<Map.Entry> を返すので注意

def map = [a: 1, b: 2, c: 4, d: 5]
def result = map.findAll { it.value % 2 == 0 }
assert result == [b: 2, c: 4]

result = map.findAll { key, value -> value % 2 == 0 }
assert result == [b: 2, c: 4]

Map drop(int num) メソッド

def strings = ['a': 10, 'b': 20, 'c': 30]
assert strings.drop(0) == ['a':10, 'b':20, 'c':30]
assert strings.drop(2) == ['c':30]
assert strings.drop(5) == [:]

Map dropWhile(Closure closure) メソッド

def shopping = [milk: 1, bread: 2, chocolate: 3]
assert shopping.dropWhile { it.key.size() < 6 } == [chocolate: 3]
assert shopping.dropWhile { it.value % 2 } == [bread: 2, chocolate: 3]
assert shopping.dropWhile { key, value -> key.size() + value <= 7 } == [chocolate: 3]

Map take(int num) メソッド

def strings = ['a': 10, 'b': 20, 'c': 30]
assert strings.drop(0) == ['a': 10, 'b': 20, 'c': 30]
assert strings.drop(2) == ['a': 10, 'b': 20]
assert strings.drop(5) == [:]

Map takeWhile(Closure closure) メソッド

def shopping = [milk: 1, bread: 2, chocolate: 3]
assert shopping.takeWhile { it.key.size() < 6 } == [milk: 1, bread: 2]
assert shopping.takeWhile { it.value % 2 } == [milk: 1]
assert shopping.takeWhile { key, value -> key.size() + value <= 7 } == [milk: 1, bread: 2]

ソートしたマップを作成

Collection sort() メソッド

キーでソートする。

def map = [b: '2', c: '1', a: '3']
def actual = map.sort()
assert actual instanceof TreeMap
assert actual*.key == ['a', 'b', 'c']

sort 後は TreeMap で返されるので、追加をしても、キーでソートされたままとなる。

def map = [e: '1', c: '3', a: '5']
def actual = map.sort()
assert actual*.key == ['a', 'c', 'e']
actual['b'] = '2'
actual['d'] = '4'
assert actual*.key == ['a', 'b', 'c', 'd', 'e']

Collection sort(Closure closure)

ソート順を指定する場合

def map = [b: '2', c: '1', a: '3']
def actual = map.sort { it.key }
assert actual instanceof LinkedHashMap
assert actual*.key == ['a', 'b', 'c']

Collection sort(Comparator comparator)

ソート順を指定する場合

def map = [b: '2', c: '1', a: '3']
def actual = map.sort { a, b -> a.key <=> b.key }
assert actual instanceof LinkedHashMap
assert actual*.key == ['a', 'b', 'c']

Collection toSorted()

値でソートする

def map = [b: '2', c: '1', a: '3']
def actual = map.toSorted()
assert actual instanceof LinkedHashMap
assert actual*.value == ['1', '2', '3']

Collection toSorted(Closure closure)

ソート順を指定する場合

def map = [b: '11', c: '1', a: '111']
def actual = map.toSorted { it.value.length() }
assert actual instanceof LinkedHashMap
assert actual*.value == ['1', '11', '111']

Collection toSorted(Comparator comparator)

ソート順を指定する場合

def map = [b: '11', c: '1', a: '111']
def actual = map.toSorted { a, b -> a.value.length() <=> b.value.length() }
assert actual instanceof LinkedHashMap
assert actual*.value == ['1', '11', '111']

更新系

def map = [a: 'A']
map.put('a', 'B')
assert map['a'] == 'B'

map.putAt('a', 'C')
assert map['a'] == 'C'

map['a'] = 'D'
assert map['a'] == 'D'

map.'a' = 'F'
assert map['a'] == 'F'

map.a = 'G'
assert map['a'] == 'G'

削除系

Object remove(Object key) メソッド

def map = [a: 'A', b: 'B', c: 'C']
def value = map.remove('b')
assert value == 'B'
assert map == [a: 'A', c: 'C']

// キーが存在しない場合
value = map.remove('d')
assert value == null
assert map == [a: 'A', c: 'C']

全削除

void clear() メソッド

def map = [a: 'A', b: 'B', c: 'C']
map.clear()
assert map == [:]

ループ系

each【非破壊】

引数が1個のクロージャの場合

def map = [a: 'A', b: 'B', c: 'C']
def keyList = []
def valueList = []
map.each { entry ->
    keyList << entry.key
    valueList << entry.value
}
assert keyList == ['a', 'b', 'c']
assert valueList == ['A', 'B', 'C']

引数が2個のクロージャの場合

def map = [a: 'A', b: 'B', c: 'C']
def keyList = []
def valueList = []
map.each { key, value ->
    keyList << key
    valueList << value
}
assert keyList == ['a', 'b', 'c']
assert valueList == ['A', 'B', 'C']

eachWithIndex メソッド

引数が2個のクロージャの場合

def map = [a: 'A', b: 'B', c: 'C']
def actualMap = [:]
def actualList = []
map.eachWithIndex { entry, i ->
    actualMap[entry.key] = entry.value
    actualList << i
}
assert actualMap == map
assert actualList == [0, 1, 2]

引数が3個のクロージャの場合

def map = [a: 'A', b: 'B', c: 'C']
def actualMap = [:]
def actualList = []
map.eachWithIndex { key, value, i ->
    actualMap[key] = value
    actualList << i
}
assert actualMap == map
assert actualList == [0, 1, 2]

reverseEach メソッド

引数が1個のクロージャの場合

def map = [a: 'A', b: 'B', c: 'C']
def keyList = []
def valueList = []
map.reverseEach {
    keyList << it.key
    valueList << it.value
}
assert keyList == ['c', 'b', 'a']
assert valueList == ['C', 'B', 'A']

引数が2個のクロージャの場合

def map = [a: 'A', b: 'B', c: 'C']
def keyList = []
def valueList = []
map.reverseEach { key, value ->
    keyList << key
    valueList << value
}
assert keyList == ['c', 'b', 'a']
assert valueList == ['C', 'B', 'A']

真偽判定系

真偽判定

  • 空マップは false
assert ![:]
  • 要素が有る場合は true
assert [0: null]

条件に一致する要素が存在するか

boolean any(Closure closure) 【非破壊】

def map = [2: 3, 4: 5, 5: 10]
assert map.any { entry -> entry.key * 2 == entry.value }
assert map.any { key, value -> key * 2 == value }

全要素が条件に一致するか

boolean every(Closure closure) 【非破壊】

def map = [a: 1, b: 2.0, c: 2L]
assert map.every { entry -> entry.value instanceof Number }
assert map.every { key, value -> value instanceof Number }

集合処理系

和集合

+ オペレータ、Map plus(Map right) メソッド【非破壊】

def map = [a: 10, b: 20, c: 30]
assert map + [d: 40, e: 50]  == [a: 10, b: 20, c: 30, d: 40, e: 50]

// キーが重複する場合は上書きされる
assert map + [a: 5, d: 40] == [a: 5, b: 20, c: 30, d: 40]

Map putAll(Collection entries)メソッド【破壊】

def map = [a: 10, b: 20, c: 30]
map.putAll([a: 15, d: 40, e: 50])
assert map  == [a: 15, b: 20, c: 30, d: 40, e: 50]

差集合

- オペレータ、Map minus(Map removeMe) メソッド【非破壊】

def map = [a: 'A', b: 'B', c: 'C']
assert map - [b: 'B'] == [a: 'A', c: 'C']

// キーと値が一致しない場合は削除されない
assert map - [b: 'D']  == [a: 'A', b: 'B', c: 'C']

積集合

Map intersect(Map right) メソッド【非破壊】

def map = [a: 'A', b: 'B', c: 'C']
assert map.intersect([b: 'B', d: 'D']) == [b: 'B']

collect

List collect(Closure transform)

assert [a: 1, b: 2].collect { entry -> entry.key * entry.value } == ['a', 'bb']
assert [a: 1, b: 2].collect { key, value -> key * value } == ['a', 'bb']

*. オペレータ

collect(Closure transform)と同じ

def map = [a: 1, b: 2, c: 3, d: 4]
assert map*.key == ['a', 'b', 'c', 'd']
assert map*.key == map.collect { it.key }

Collection collect(Collection collector, Closure transform)

assert [a: 1, b: 2].collect([] as HashSet) { entry -> entry.key * entry.value } == ['a', 'bb'] as Set
assert [a: 1, b: 2].collect([] as HashSet) { key, value -> key * value } == ['a', 'bb'] as Set

collectEntries

Map collectEntries(Closure transform) メソッド

assert [a: 1, b: 2].collectEntries { key, value -> [value, key] } == [1: 'a', 2: 'b']
assert [a: 1, b: 2].collectEntries { key, value -> [(value * 10): key.toUpperCase()] } == [10: 'A', 20: 'B']

Map collectEntries(Map collector, Closure transform) メソッド

assert [a: 1, b: 2].collectEntries([:]) { key, value -> [value, key] } == [1: 'a', 2: 'b']
assert [a: 1, b: 2].collectEntries([30: 'C']) { key, value -> [(value * 10): key.toUpperCase()] } == [10: 'A', 20: 'B', 30: 'C']

グループ化

Map groupBy(Closure closure)

def result = [a: 1, b: 2, c: 3, d: 4, e: 5, f: 6].groupBy { it.value % 2 }
assert result == [0: [b: 2, d: 4, f: 6], 1: [a: 1, c: 3, e: 5]]

result = [a: 1, b: 2, c: 3, d: 4, e: 5, f: 6].groupBy { key, value -> value % 2 }
assert result == [0: [b: 2, d: 4, f: 6], 1: [a: 1, c: 3, e: 5]]

Map groupBy(Object closures)

def result = [a:1,b:2,c:3,d:4,e:5,f:6].groupBy({ it.value % 2 }, { it.key.next() })
assert result == [1: [b: [a: 1], d: [c: 3], f: [e: 5]], 0: [c: [b: 2], e: [d: 4], g: [f: 6]]]

Map groupBy(List closures)

def result = [a:1,b:2,c:3,d:4,e:5,f:6].groupBy([{ it.value % 2 }, { it.key.next() }])
assert result == [1: [b: [a: 1], d: [c: 3], f: [e: 5]], 0: [c: [b: 2], e: [d: 4], g: [f: 6]]]

inject

Object inject(Object initalValue, Closure closure)

def map = [a: 1, b: 2, c: 3]
assert map.inject([]) { result, entry -> result + [entry.key] * entry.value } == ['a', 'b', 'b', 'c', 'c', 'c']
assert map.inject([]) { result, key, value -> result + [key] * value } == ['a', 'b', 'b', 'c', 'c', 'c']

その他のオペレータ系

*:オペレータ

def map = [c: 3, d: 4]
assert [a: 1, b: 2, *:m1] == [a: 1, b: 2, c: 3, d: 4]

その他

  • findResult:?
  • findResults:?
  • groupEntriesBy:説明難しい

コメント