Home > Groovy > A quirk in Groovy maps and GString coercion

A quirk in Groovy maps and GString coercion

I slipped into my old Java ways recently and lost a bit of Groovy magic in the process. I was calling the get method on a map and getting null back, though I was quite confident I should have gotten a value from the map.

Let’s start with a simple map in Groovy:

def map = [a:’x’,b:’y’,c:’z’]

 

Now we can print out the value for key ‘a’ with magical Groovy syntax:

println map[‘a’]  // this outputs x

 

Or we can slip back into our old Java ways and it will still works.

println map.get(‘a’) // this also outputs x

 

But what if we want to look up a value using a GString with an inner variable instead of the normal String?

def aVar = ‘a’

println map[“$aVar”] // still good, this outputs x

println map.get(“$aVar”) // oh snap! this outputs null!

 

As you can see, using the Java style of .get() using a GString that contains a variable doesn’t work.

 

But… wait a second! Aren’t ‘a’ and “$aVar” supposed to be the same thing in Groovy!?

println ‘a’ == “$aVar” // true

 

Not entirely. Yes, you learned that == in Groovy is the same as calling .equals in Java. But check this out!

println ‘a’.equals(“$aVar”) // double snap!! it’s false!!

 

So == obviously isn’t exactly the same as .equals – if you check out the Groovy Operator Overloading page, you’ll see a little sidenote:

** Note: The == operator doesn’t always exactly match the .equals() method. You can think of them as equivalent in most situations. In situations where two objects might be thought “equal” via normal Groovy “coercion” mechanisms, the == operator will report them as equal; the .equals() method will not do so if doing so would break the normal rules Java has around the equals method. Expect further improvements to Groovy over time to provide clearer, more powerful and more consistent behavior in this area.

 

In case you’ve read that sidenote before but you didn’t know what it meant by “coercion” mechanisms, now you know.

Keep all this in mind next time you’re dealing with a map in Groovy. Stick to using the Groovy array-ish square brackets instead of using the traditional .get() and you’ll avoid a potential headache.

Advertisements
Tags:
  1. Fergus Byrne
    November 26, 2010 at 2:33 pm

    I came across another inconsistency when using Assert.

    testGStringEquals(){
    String a = “a”
    assertEquals(“$a”, a)
    }

    Results in
    java.lang.AssertionError: expected: org.codehaus.groovy.runtime.GStringImpl but was: java.lang.String

  1. November 17, 2008 at 9:47 pm

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: