倭マン's BLOG

くだらない日々の日記書いてます。 たまにプログラミング関連の記事書いてます。 書いてます。

Groovy in Addiction (10) : マップ Map

今回はマップ (java.util.Map) について。 『Groovyイン・アクション』Chapter4 とGroovy JDKを参考にしています(一覧)。

Groovyイン・アクション

Groovyイン・アクション

Generics は Map<K, V> に対して呼び出しています。

インスタンス生成

def map1 = ['a':1, 'b':2, 'c':3];
assert map1 instanceof LinkedHashMap;

def map2 = ['a':1, 'b':2, 'c':3] as TreeMap;
assert map2 instanceof TreeMap;

//***** 空マップ *****
def emptyMap = [:];
assert emptyMap instanceof LinkedHashMap;
assert emptyMap.size() == 0;

//***** 文字列キーに対する略記法 *****
assert [a:1, b:2, c:3] == ['a':1, 'b':2, 'c':3];

x = 'a';
assert ['x':1] == [x:1];
assert ['a':1] == [(x):1];

//***** マップ展開演算子 *****
def map3 = [*:[a:1, b:2], c:3, ];
assert map3 == [a:1, b:2, c:3];

inmap = [a:1, b:2];
def map4 = [*:inmap, c:3];
assert map4 == [a:1, b:2, c:3];

クラスを指定しない場合は java.util.LinkedHashMapインスタンスが返されます。 このため、暗黙の内にエントリの順序は保存されます。

値・エントリの取得と設定:get & put

メソッド名 返り値 メソッド名
(Generics)
返り値
(Generics)
get(Object, Object) Object get(K, V) V
getAt(Object) Object getAt(K) V
find(Closure) Entry find(Closure<Entry<K, V>, boolean>)
find(Closure<K, V, boolean>)
Entry<K, V>
putAt(Object, Object) Object putAt(K, V) V
putAll(Collection) Map putAll(Collection<Entry<K, V>>) Map<K, V>
plus(Map)
plus(Collection)
Map plus(Map<K, V>)
plus(Collection<Entry<K, V>>)
Map<K, V>
leftShift(Entry) Map leftShift(Entry<K, V>) Map<K, V>
map = [a:1, b:2, c:3];

//***** get(), getAt() *****
assert map.get('a') == 1;
assert map.get('a', 0) == 1;
assert map['a'] == 1;
assert map.a == 1;

assert map.get('d') == null;
assert map['d'] == null;
assert map.d == null;

assert map.get('d', 0) == 0;    // デフォルト値の指定(設定)
assert map.d == 0;

//***** find() *****
found = map.find { entry -> entry.value < 2 };
assert found.key == 'a';
assert found.value == 1;

found = map.find { key, value -> value < 2 };
assert found.key == 'a';
assert found.value == 1;

//***** putAt() *****
map['d'] = 1;
assert map.d == 1;

map.d = 2;
assert map.d == 2;

map = ['a.b':1, 'package':2];
assert map.'a.b' == 1;
assert map.'package' == 2;

//***** plus(), leftShift() *****
map1 = [a:1, b:2, c:3];
map2 = [d:4, e:5];

map = map1 + map2;
assert map == [a:1, b:2, c:3, d:4, e:5];

map3 = [f:6, g:7];
map3.each { entry -> map << entry };
assert map == [a:1, b:2, c:3, d:4, e:5, f:6, g:7];
  • キーをプロパティのように扱えます(map.a とか)。
  • find() の引数のクロージャは、宣言した変数の個数によって渡される値が異なります。 これは下記で見ていく、クロージャを引数として取る他のメソッドについても同じです。
    • 1個のときは、エントリ (Map$Entry) オブジェクト
    • 2個のときは、順にキーと値

boolean を返すメソッド

メソッド名 返り値 メソッド名
(Generics)
返り値
(Generics)
asBoolean() boolean
any(Closure) boolean any(Closure<Entry<K, V>, boolean>)
any(Closure<K, V, boolean>)
boolean
every(Closure) boolean every(Closure<Entry<K, V>, boolean>)
every(Closure<K, V, boolean>)
boolean
//***** asBoolean() *****
map = [a:1];
if(map)
    assert true;
else
    assert false;

map = [:];
if(map)
    assert false;
else 
    assert true;

//***** any(), every() *****
map = [a:1, b:2, c:3];
assert map.any { entry -> entry.value > 2 };
assert map.every { entry -> entry.key < 'd' };
  • Collection 型と同様に、Map#asBoolean() もなら false、そうでないなら true を返します。
  • any(), every() の引数のクロージャも、find() と同様に、引数を2つにすれば「キーと値」が渡されます。

コレクション、Map を返すメソッド

メソッド名 返り値 メソッド名
(Generics)
返り値
(Generics)
each(Closure) Map each(Closure<Entry<K, V>, void>)
each(Cosure<K, V, void>)
Map<K, V>
eachWithIndex(Closure) Map eachWithIndex(Closure<Entry<K, V, int>, void>)
each(Cosure<K, V, int, void>)
Map<K, V>
collect(Closure) List collect(Closure<Entry<K, V>, R>)
collect(Closure<K, V, R>)
List<R>
collect(Collection, Closure) Collection collect(Collection<R>, Closure<Entry<K, V>, R>)
collect(Collection<R>, Closure<K, V, R>)
Collection<R>
findAll(Closure) Map findAll(Closure<Entry<K, V>, boolean>)
findAll(Closure<K, V, boolean>)
Map<K, V>
subMap(Collection) Map subMap<Collection<K>> Map<K, V>
sort(Closure) Map sort(Closure<Entry<K, V>, Comparable<?>>)
sort(Closure<Entry<K, V>, Entry<K, V>, int>)
Map<K, V>
withDefault(Closure) Map
groupBy(Closure) Map groupBy(Closure<Entry<K, V>, R>)
groupBy(Closure<K, V, R>)
Map<R, Map<K, V>>
groupEntriesBy(Closure) Map groupEntriesBy(Closure<Entry<K, V>, R>)
groupEntriesBy(Closure<K, V, R>)
Map<R, Entry<K, V>>
asImmutable() Map
asSynchronized() Map
map = [a:1, b:2, c:3];

//***** each(), eachWithIndex() *****
store = [];
map.each { entry -> store << [entry.key, entry.value] };
assert store == [['a', 1], ['b', 2], ['c', 3]];

store = [];
map.each { key, value -> store << [key, value] };
assert store == [['a', 1], ['b', 2], ['c', 3]];

store = [];
map.eachWithIndex { entry, i -> store << [entry.key, entry.value, i] };
assert store == [['a', 1, 0], ['b', 2, 1], ['c', 3, 2]];

store = [];
map.eachWithIndex { key, value, i -> store << [key, value, i] };
assert store == [['a', 1, 0], ['b', 2, 1], ['c', 3, 2]];

//***** collect() *****
result = map.collect { entry -> entry.value*2 };
assert result == [2, 4, 6];

result = map.collect { key, value -> value*value };
assert result == [1, 4, 9];

//***** findAll() *****
result = map.findAll { key, value -> value < 3 };
assert result == [a:1, b:2];

//***** subMap() *****
result = map.subMap(['a', 'b']);
assert result == [a:1, b:2];

set = ['a', 'b'] as Set;
result = map.subMap(set);
assert result == [a:1, b:2];

//***** sort() *****
map = [a:5, b:4, c:3, d:2, e:1];

result = map.sort{ entry -> entry.value };
assert result == [e:1, d:2, c:3, b:4, a:5];

result = map.sort{ a, b -> a.value <=> b.value };
assert result == [e:1, d:2, c:3, b:4, a:5];

//***** withDefault() *****
//map = [a:1, b:2].withDefault{ k -> k.toCharacter().isLowerCase() ? 10 : -10 };
//expected = [a:1, b:2, c:10, D:-10];
//assert expected.every{ e -> e.value == map[e.key] };
//
//constMap = [:].withDefault{ 42 };
//assert constMap.foo == 42;
//assert constMap.size() == 1;

//***** groupBy() *****
map = [a:1,b:2,c:3,d:4,e:5,f:6];
result = map.groupBy { it.value % 2 };
assert result == [0:[b:2, d:4, f:6], 1:[a:1, c:3, e:5]];

n = 0; 0.upto(result.size()-1){ i -> n += result[i].size() };
assert n == map.size();

//***** groupEntriesBy() *****
result = [a:1,b:2,c:3,d:4,e:5,f:6].groupEntriesBy { it.value % 2 };
assert result.toString() == '[1:[a=1, c=3, e=5], 0:[b=2, d=4, f=6]]'; 
assert result[0]*.key == ['b', 'd', 'f'];
assert result[0]*.value == [2, 4, 6];
assert result[1]*.key == ['a', 'c', 'e'];
assert result[1]*.value == [1, 3, 5];

n = 0; 0.upto(result.size()-1){ i -> n += result[i].size() };
assert n == map.size();
  • each(), eachWithIndex() は通常返り値の Map は使わないでしょう。
  • withDefault() は Groovy JDK に載っているサンプルが動かなかったので無視。

その他のメソッド

メソッド名 返り値
asType(Class) Object
toMapString() String
spread() SpreadMap
toSpreadMap() SpreadMap
  • SpreadMap?