Loop through Map in Groovy?

Go To StackoverFlow.com

156

I have a very simple task I am trying to do in Groovy but cannot seem to get it to work. I am just trying to loop through a map object in groovy and print out the key and value but this code does not work.

// A simple map
def map = [
        iPhone : 'iWebOS',
        Android: '2.3.3',
        Nokia  : 'Symbian',
        Windows: 'WM8'
]

// Print the values
for (s in map) {
    println s + ": " + map[s]
}

I am trying to get the output to look like this:

iPhone: iWebOS
Android: 2.3.3
Nokia: Symbian
Windows: WM8

Could someone please elaborate on how to do this??

2012-04-05 23:20
by Kevin
As you have seen in the answers, the problem is that iterating over a map gives you a collection of "Entries", you were assuming it would give you the keys and you would look up the values. If you wanted to do it that way, iterate over map.keySet() and the rest will work as you expected - Bill K 2017-06-13 15:51
It should work if you use s.key & s.value in your code inside for loop - inblueswithu 2017-11-14 20:25


293

Quite simple with a closure:

def map = [
           'iPhone':'iWebOS',
           'Android':'2.3.3',
           'Nokia':'Symbian',
           'Windows':'WM8'
           ]

map.each{ k, v -> println "${k}:${v}" }
2012-04-05 23:23
by Jack
Out of curiosity, where is this documented in the Groovy language docs (I don't think it is!)? I guess I'm wondering, from a Groovy newbies' perspective, How did you know this?smeeb 2015-10-24 10:40
@smeeb: everything is well documented, take a look here: http://www.groovy-lang.org/groovy-dev-kit.html#iteratingon_map - Jack 2015-10-24 15:26


88

Alternatively you could use a for loop as shown in the Groovy Docs:

def map = ['a':1, 'b':2, 'c':3]
for ( e in map ) {
    print "key = ${e.key}, value = ${e.value}"
}

/*
Result:
key = a, value = 1
key = b, value = 2
key = c, value = 3
*/

One benefit of using a for loop as opposed to an each closure is easier debugging, as you cannot hit a break point inside an each closure (when using Netbeans).

2013-04-19 19:08
by ubiquibacon
I use GGTS 3.2 and routinely set break points in closures (including "each" closures). The problem is using F6 to step through a closure, as it will go over the whole thing. Technically, you can hit F5 a bunch of times and eventually end up in there, but a break point is faster - Philip 2013-05-20 09:35
Updated answer. I am using Netbeans and its debugging of Groovy/Grails is sub-par - ubiquibacon 2013-05-20 13:56
Plus you can break out a for loop and not in .each - Alexander Suraphel 2015-02-17 14:48
@AlexanderSuraphel you are correct that you cannot use break to exit each, but you can use returnubiquibacon 2015-07-21 14:30
@ubiquibacon no you can't. return is analogous to continue not break - Alexander Suraphel 2015-07-21 15:59
@AlexanderSuraphel Ah, so it is - ubiquibacon 2015-07-21 19:50
The disadvantage of using for loop is that if you have an empty map you will have error like this: Ambiguous expression could be either a parameterless closure expression or an isolated open code block; solution: Add an explicit closure parameter list, e.g. {it -> ...}, or force it to be treated as an open block by giving it a label, e.g. L:{...} @ line 1, column 1. { - tstempko 2016-02-02 08:56
Another reason to use this way: currently you can't use .each in jenkins groovy sandbox FAILURE: Jenkins exception: java.lang.UnsupportedOperationException: Calling public static java.util.Map org.codehaus.groovy.runtime.DefaultGroovyMethods.each(java.util.Map,groovy.lang.Closure) on a CPS-transformed closure is not yet supported (JENKINS-26481); encapsulate in a @NonCPS method, or use Java-style loopsAvner 2017-09-28 01:12


17

When using the for loop, the value of s is a Map.Entry element, meaning that you can get the key from s.key and the value from s.value

2012-04-06 06:15
by sbglasius
Thanks for explaining why the OP's code doesn't wor - dj18 2016-02-24 17:06


12

Another option:

def map = ['a':1, 'b':2, 'c':3]
map.each{
  println it.key +" "+ it.value
}
2016-01-19 00:12
by Pablo Pazos
Ads