A map is a collection of (key, value) pairs. It is commonly used for implementing lookups or cache. For example, if it is complicated and takes a lot of time to compute a person's salary, we can have:
def salaryMap = [:] salaryMap['John'] = computeBasicPay('John') + computeDeductions('John') salaryMap['Peter'] = computeBasicPay('Peter') + computeDeductions('Peter') salaryMap['Mark'] = computeBasicPay('Mark') + computeDeductions('Mark')
We can utilize a map such that computations are performed only once. Once the map is populated, looking up a value is very fast!
println "Salary of John is: ${salaryMap['John']}"
We can lookup the values as often as needed without the complex computation penalty.
In Groovy and Grails, maps can also be used like beans. In fact, this is not uncommon and are often seen in Grails projects. For example:
def personDetails = [firstName:'John', lastName:'Doe', age:25] println "First Name: ${personDetails.firstName}" println "Last Name: ${personDetails.lastName}" println "Age: ${personDetails.age}"
As you could see, the keys are used like property getter/setter.
Note: A Groovy map is an instance of java.util.Map
This is how to declare an empty map
def emptyMap = [:]
The colon inside the square brackets denotes that the object is a map and not a list.
Map Literal Values
This is how to declare a map with initial values
def sampleMap = [color:'Blue', shape:'Circle']
The keys are String by default when written plainly without quotes (E.g. color instead of 'color' or "color"). The above declaration is the same as:
def sampleMap = ['color':'Blue', 'shape':'Circle'] def sampleMap2 = ["color":'Blue', "shape":'Circle']
We can use instance of other classes (aside from String) as keys or values
def sampleMap = [99:new Long(99), (BigDecimal.valueOf(5)):new Double(5)]
These are the different ways of adding values to a map.
def sampleMap = [:] sampleMap.put('thickness', 10) sampleMap['color'] = 'Blue' sampleMap.weight = 500 sampleMap.'shape' = 'Circle' sampleMap << [price:150]
This map will have equivalent values as this:
def sampleMap = [color:'Blue', weight:500, shape:'Circle', thickness:10, price:150]As you could see, we are allowed to:
Updating values from an existing map is the same as adding values. The statement will just replace the existing value if it already exists in the map. For example:
def sampleMap = [color:'Blue', weight:500, shape:'Circle', thickness:10, price:150] sampleMap['color'] = 'Red' sampleMap.'shape' = 'Rectangle' sampleMap.weight = 200 sampleMap.put('thickness', 5) sampleMap << [price:99]
Will have this resulting value:
[color:'Red', shape:'Rectangle', weight:200, thickness:5, price:99]
Here are some samples on how to remove values from a map.
def sampleMap = [color:'Blue', weight:500, shape:'Circle', thickness:10, price:150] sampleMap.remove('color') sampleMap = sampleMap - ['shape':'Circle'] sampleMap -= [weight:500]
We could use remove or subtraction of map if you know the exact key value pair. The result of the above code is:
[thickness:10, price:150]
Retrieving values from a Groovy Map is straightforward
def sampleMap = [color:'Blue', weight:500, shape:'Circle', thickness:10, price:150] println "The color is: ${sampleMap.get('color')}" println "The weight is: ${sampleMap['weight']}" println "The shape is: ${sampleMap.shape}" println "The thickness is: ${sampleMap.'thickness'}"
Here are some Map manipulation tricks that makes Groovy fun to use:
assert 'Red' == [color:'Red', shape:'blue'].get('color', 'Blue') assert 'Blue' == [shape:'blue'].get('color', 'Blue')The first statement returns Red because color is in the key set. The second statement returns the default value Blue because color is not in the key set.
def wordList = ['Apple', 'Banana', 'Cat'] def wordCountMap = wordList.collectEntries{ [(it):it.length()] }Results to this values:
[Apple:5, Banana:6, Cat:3]
def wordList = ['Apple', 'Banana', 'Cat'] def wordCountMap = wordList.collectEntries{ [(it):it.length()] } def longWords = wordCountMap.count { key, value-> value >= 4 } println "${longWords}"This will result to the answer 2 because only 2 words have length greater than or equal to 4.
We can add maps to combine their contents
def map1 = [p1:100, p2:200] def map2 = [p3:300, p4:400] def map3 = map1 + map2 println "${map3}"
This will result to
[p1:100, p2:200, p3:300, p4:400]
We can get the intersection of two maps
def map1 = [p1:100, p2:200, p3:300, p4:400, p5:500] def map2 = [p4:400, p5:500, p6:600, p7:700] def map3 = map1.intersect(map2) println "${map3}"This will result to
[p4:400, p5:500]
def map1 = [p1:100, p2:200, p3:300, p4:400, p5:500] println "${map1.keySet()}"This will print
[p1, p2, p3, p4, p5]
def map1 = [p1:100, p2:200, p3:300, p4:400, p5:500] println "${map1.values()}"This will print
[100, 200, 300, 400, 500]
def map1 = [p1:100, p2:200, p3:300, p4:400, p5:500] println "${map1.min {it.key}}" println "${map1.min {it.value}}"Both println will result
p1=100
def map1 = [p1:100, p2:200, p3:300, p4:400, p5:500] println "${map1.max {it.key}}" println "${map1.max {it.value}}"Both println will result
p5=500