1. 概要

Groovy は、JavaMap APIをに拡張し、フィルタリング、検索、並べ替えなどの操作のメソッドを提供します。 また、 マップを作成および操作するためのさまざまな簡単な方法。 

このチュートリアルでは、Groovyによるマップの操作方法を見ていきます。

2. Groovyマップの作成

マップリテラル構文[k:v]を使用してマップを作成できます。基本的に、マップをインスタンス化し、1行でエントリを定義できます。

空のマップは、次を使用して作成できます。

def emptyMap = [:]

同様に、値を持つマップは、以下を使用してインスタンス化できます。

def map = [name: "Jerry", age: 42, city: "New York"]

キーは引用符で囲まれていないことに注意してください。デフォルトではndであり、Groovyはjava.util.LinkedHashMap。のインスタンスを作成します。 as演算子。

3. アイテムの追加

マップを定義することから始めましょう:

def map = [name:"Jerry"]

マップにキーを追加できます。

map["age"] = 42

ただし、もう1つのJavascriptに似た方法は、プロパティ表記(ドット演算子)を使用することです。

map.city = "New York"

つまり、Groovyは、Beanのような方法でキーと値のペアのアクセスをサポートします。

マップに新しいアイテムを追加するときに、リテラルの代わりに変数をキーとして使用することもできます。

def hobbyLiteral = "hobby"
def hobbyMap = [(hobbyLiteral): "Singing"]
map.putAll(hobbyMap)
assertTrue(hobbyMap.hobby == "Singing")
assertTrue(hobbyMap[hobbyLiteral] == "Singing")

まず、キー hobbyを格納する新しい変数を作成する必要があります。次に、括弧で囲まれたこの変数をマップリテラル構文とともに使用して、別のマップを作成します。

4. アイテムの取得

リテラル構文またはプロパティ表記を使用して、マップからアイテムを取得できます。

次のように定義されたマップの場合:

def map = [name:"Jerry", age: 42, city: "New York", hobby:"Singing"]

キーnameに対応する値を取得できます。

assertTrue(map["name"] == "Jerry")

また

assertTrue(map.name == "Jerry")

5. アイテムの削除

キーに基づいてマップからエントリを削除するには、 削除する() 方法ですがマップから複数のエントリを削除する必要がある場合があります。 これは、minus()メソッドを使用して実行できます。

minus()メソッドは、 Map を受け入れ、基になるマップから指定されたマップのすべてのエントリを削除した後、新しいMapを返します。

def map = [1:20, a:30, 2:42, 4:34, ba:67, 6:39, 7:49]

def minusMap = map.minus([2:42, 4:34]);
assertTrue(minusMap == [1:20, a:30, ba:67, 6:39, 7:49])

次に、条件に基づいてエントリを削除することもできます。 これは、 removeAll()メソッドを使用して実現できます。

minusMap.removeAll{it -> it.key instanceof String}
assertTrue(minusMap == [1:20, 6:39, 7:49])

逆に、条件を満たすすべてのエントリを保持するには、 reservedAll()メソッドを使用できます。

minusMap.retainAll{it -> it.value % 2 == 0}
assertTrue(minusMap == [1:20])

6. エントリの反復

each()を使用して、エントリ反復できます。 およびeachWithIndex()メソッド。

each()メソッドは、現在のエントリに対応する entry key value、などの暗黙的なパラメータを提供します

eachWithIndex()メソッドは、Entryに加えてインデックスも提供します。 どちらのメソッドも、引数としてClosureを受け入れます。

次の例では、それぞれを繰り返し処理しますエントリ。 The 閉鎖に渡されます各() メソッドは、暗黙のパラメータエントリからキーと値のペアを取得し、それを出力します。

map.each{entry -> println "$entry.key: $entry.value"}

次に、 eachWithIndex()メソッドを使用して、現在のインデックスを他の値と一緒に出力します。

map.eachWithIndex{entry, i -> println "$i $entry.key: $entry.value"}

キー値、とインデックスを別々に提供するように依頼することもできます。

map.eachWithIndex{key, value, i -> println "$i $key: $value"}

7. フィルタリング

find()、findAll()、、および grep()メソッドを使用して、キーと値に基づいてマップエントリをフィルタリングおよび検索できます。

これらのメソッドを実行するためのマップを定義することから始めましょう。

def map = [name:"Jerry", age: 42, city: "New York", hobby:"Singing"]

最初に、 find()メソッドを確認します。このメソッドは、 Closure を受け入れ、Closureに一致する最初のEntryを返します。調子:

assertTrue(map.find{it.value == "New York"}.key == "city")

同様に、 findAllClosure、を受け入れますが、Closureの条件を満たすすべてのキーと値のペアを持つMapを返します。 :

assertTrue(map.findAll{it.value == "New York"} == [city : "New York"])

リストを使用したい場合は、findAllの代わりにgrepを使用できます。

map.grep{it.value == "New York"}.each{it -> assertTrue(it.key == "city" && it.value == "New York")}

最初にgrepを使用して、値がNewYorkのエントリを検索しました。 次に、戻りタイプが List、であることを示すために、 grep()。の結果を繰り返し処理します。暗黙のパラメータ。期待される結果かどうかを確認します。

次に、マップ内のすべてのアイテムが条件を満たすかどうかを確認するために、 every、を使用してbooleanを返します。

マップ内のすべての値がStringタイプであるかどうかを確認しましょう。

assertTrue(map.every{it -> it.value instanceof String} == false)

同様に、 any を使用して、マップ内のアイテムが条件に一致するかどうかを判断できます。

assertTrue(map.any{it -> it.value instanceof String} == true)

8. 変換と収集

マップ内のエントリを新しい値に変換したい場合があります。 collect()メソッドとcollectEntries()メソッドを使用して、エントリをそれぞれコレクションまたはマップに変換および収集することができます。

いくつかの例を見てみましょう。 従業員IDと従業員のマップが与えられた場合:

def map = [
  1: [name:"Jerry", age: 42, city: "New York"],
  2: [name:"Long", age: 25, city: "New York"],
  3: [name:"Dustin", age: 29, city: "New York"],
  4: [name:"Dustin", age: 34, city: "New York"]]

collect()を使用して、すべての従業員の名前をリストに収集できます。

def names = map.collect{entry -> entry.value.name}
assertTrue(names == ["Jerry", "Long", "Dustin", "Dustin"])

次に、一意の名前のセットに関心がある場合は、Collectionオブジェクトを渡すことでコレクションを指定できます。

def uniqueNames = map.collect([] as HashSet){entry -> entry.value.name}
assertTrue(uniqueNames == ["Jerry", "Long", "Dustin"] as Set)

マップ内の従業員名を小文字から大文字に変更する場合は、collectEntriesを使用できます。 このメソッドは、変換された値のマップを返します。

def idNames = map.collectEntries{key, value -> [key, value.name]}
assertTrue(idNames == [1:"Jerry", 2:"Long", 3:"Dustin", 4:"Dustin"])

最後に、 collectメソッドをfindおよびfindAllメソッドと組み合わせて使用して、フィルター処理された結果を変換することもできます。

def below30Names = map.findAll{it.value.age < 30}.collect{key, value -> value.name}
assertTrue(below30Names == ["Long", "Dustin"])

ここでは、20〜30歳のすべての従業員を検索し、それらをマップに収集します。

9. グループ化

マップの一部のアイテムを条件に基づいてサブマップにグループ化したい場合があります。

groupBy()メソッドはマップのマップを返し、各マップには、指定された条件に対して同じ結果と評価されるキーと値のペアが含まれています。

def map = [1:20, 2: 40, 3: 11, 4: 93]
     
def subMap = map.groupBy{it.value % 2}
assertTrue(subMap == [0:[1:20, 2:40], 1:[3:11, 4:93]])

サブマップを作成する別の方法は、subMap()を使用することです。 groupBy()とは異なり、キーに基づいたグループ化のみが可能です。

def keySubMap = map.subMap([1,2])
assertTrue(keySubMap == [1:20, 2:40])

この場合、キー1と2のエントリは新しいマップに返され、他のすべてのエントリは破棄されます。

10. 並べ替え

通常、並べ替えるときは、キーまたは値、あるいはその両方に基づいてマップ内のエントリを並べ替えることができます。 Groovyは、この目的に使用できる sort()メソッドを提供します。

与えられた地図:

def map = [ab:20, a: 40, cb: 11, ba: 93]

キーで並べ替えを行う必要がある場合は、自然順序付けに基づく引数なしの sort()メソッドを使用します。

def naturallyOrderedMap = map.sort()
assertTrue([a:40, ab:20, ba:93, cb:11] == naturallyOrderedMap)

または、 sort(Comparator)メソッドを使用して、比較ロジックを提供することもできます。

def compSortedMap = map.sort({k1, k2 -> k1 <=> k2} as Comparator)
assertTrue([a:40, ab:20, ba:93, cb:11] == compSortedMap)

次に、キー、値、またはその両方で並べ替えるために、sort()にクロージャー条件を指定できます。

def cloSortedMap = map.sort({it1, it2 -> it1.value <=> it1.value})
assertTrue([cb:11, ab:20, a:40, ba:93] == cloSortedMap)

11. 結論

この記事では、GroovyでMapを作成する方法を学びました。 次に、マップからアイテムを追加、取得、および削除するさまざまな方法を検討しました。

最後に、フィルタリング、検索、変換、並べ替えなどの一般的な操作を実行するためのGroovyのすぐに使用できるメソッドについて説明しました。

いつものように、この記事で取り上げられている例は、GitHub。にあります。