Dictionary 如果在没有Java8的Groovy中不存在,则放入映射

Dictionary 如果在没有Java8的Groovy中不存在,则放入映射,dictionary,groovy,Dictionary,Groovy,我需要把一个条目的地图,只有当钥匙还没有出现。对于Java8,我只想使用putIfAbsent,但我将Groovy用于Java7 说明问题的代码: def map = [a: 1, b: 2, c: 3] def newEntries = [a: 11, b: 22, d: 44] def result = // put new entries to the map only if they are not present assert result == [a: 1, b: 2, c: 3

我需要把一个条目的地图,只有当钥匙还没有出现。对于Java8,我只想使用
putIfAbsent
,但我将Groovy用于Java7

说明问题的代码:

def map = [a: 1, b: 2, c: 3]
def newEntries = [a: 11, b: 22, d: 44]

def result = // put new entries to the map only if they are not present

assert result == [a: 1, b: 2, c: 3, d: 44]

是否可以使用Groovy的某些功能来执行此操作,或者我需要手动执行此操作?

您可以自己使用元编程:

Map.metaClass.putIfAbsent = { otherMap ->
    otherMap.each { k, v ->
        if (! delegate.keySet().contains(k)) {
            delegate.put(k, v)
        }
    }
    delegate
}

def map = [a: 1, b: 2, c: 3]
def newEntries = [a: 11, b: 22, d: 44]

def result = map.putIfAbsent(newEntries)

assert [a: 1, b: 2, c: 3, d: 44] == result

我刚刚发现这同样有效:

def map = [a: 1, b: 2, c: 3]
def newEntries = [a: 11, b: 22, d: 44]

def result = newEntries + map

assert result == [a: 1, b: 2, c: 3, d: 44]
用原始条目覆盖默认条目就足够了。

的解决方案非常优雅,但您也可以使用Java 1.5中引入的,并提供了方法。因此,您可以将代码实现为:

import java.util.concurrent.ConcurrentHashMap;
def map = new ConcurrentHashMap([a: 1, b: 2, c: 3])

[a: 11, b: 22, d: 44].each() { k,v ->
    map.putIfAbsent(k,v);
}

assert [a: 1, b: 2, c: 3, d: 44] == map;

还有Groovy的
Map.withDefault()
方法,它非常灵活,但可以用于此目的。行为可能会有所不同,因为默认值在第一次请求之前不会实际添加到映射中:

def map = [a: 1, b: 2, c: 3]
def newEntries = [a: 11, b: 22, d: 44]

def result = map.withDefault { k -> newEntries[k] }

assert result == map
assert result != [a: 1, b: 2, c: 3, d: 44]
assert newEntries.keySet().every { k -> result[k] == map[k] ?: newEntries[k] }
assert result == [a: 1, b: 2, c: 3, d: 44]

它不是重复的吗:?不,我不需要
Multimap
,只要
HashMap
就可以解决我的问题是的,很好-但是
ConcurrentHashMap
创建了很多
ConcurrentHashMap$Segment
ConcurrentHashMap$HashEntry[]
ReentrantLock$NonfairSync
在内存中,对于如此简单的操作,看起来有点过分:)