Search code examples
dictionarygroovyidioms

Idiomatic/Groovy way to add two maps, either of which may be null


I have the following map:

configs = [
    common : [
            foo : '123',
            bar : '456'
    ],
    dev : [
            foo : '789',
            bar : '012'
    ],
    test : null
]

When I add dev to common, it works great - the values from common are overridden by the values from dev. Just what I want.

dev = configs['common'] + configs['dev']
println dev
// --> [foo:789, bar:012]

However, if I try the same with test, I get the following error:

groovy.lang.GroovyRuntimeException: Ambiguous method overloading for method java.util.LinkedHashMap#plus. Cannot resolve which method to invoke for [null] due to overlapping prototypes between: [interface java.util.Collection] [interface java.util.Map]

I can make it work by doing something like the following:

test = [:]
test = configs['common']==null ? test : test + configs['common']  // First add common bits
test = configs['test']==null ? test : test + configs['test']  // Then override with environment specific bits
println test
// --> [foo:123, bar:456]

But this seems ugly and bloated.

Can someone with better Groovy-fu show me a nicer way? Thanks!


Solution

  • You can use Elvis operator to bring an empty map to the equation when config['test'] == null. Consider the following example:

    def configs = [
      common : [
        foo : '123',
        bar : '456'
      ],
      dev : [
        foo : '789',
        bar : '012'
      ],
      test : null
    ]
    
    
    def dev = configs['common'] + (configs['dev'] ?: [:])
    println dev
    
    def test = configs['common'] + (configs['test'] ?: [:])
    println test
    

    Output:

    [foo:789, bar:012]
    [foo:123, bar:456]
    

    You can use it whenever you expect that one value can be represented by null.