我用Groovy地图问题。 我一直在寻找一种方法以编程方式添加新条目到Groovy的地图,而不会覆盖当前条目。 例如
def editsMap = [:]
lineEdits.flag.each
{ lineEdits_Flag ->
editsMap.put('FlagId',lineEdits_Flag.id)
editsMap.put('FlagMnemonic',lineEdits_Flag.mnemonic)
editsMap.put('Action',lineEdits_Flag.action)
println "editsMap: ${editsMap}"
}
第一遍产生此地图:
editsMap:FlagId:10001,FlagMnemonic:TRA,动作:评论]
但在第二遍覆盖第一遍与:editsMap:[FlagId:10002,FlagMnemonic:REB,动作:拒绝]
我想要做的就是创建一个地图内的多个条目。 我需要我的地图来填充是这样的:
editsMap: [FlagId:10001, FlagMnemonic:TRA, Action:review]
editsMap: [FlagId:10002, FlagMnemonic:REB, Action:deny]
editsMap: [FlagId:10003, FlagMnemonic:UNB, Action:deny]
editsMap: [FlagId:20001, FlagMnemonic:REB, Action:deny]
editsMap: [FlagId:20002, FlagMnemonic:ICD, Action:review]
editsMap: [FlagId:30001, FlagMnemonic:REB, Action:deny]
editsMap: [FlagId:40001, FlagMnemonic:ICD, Action:review]
editsMap: [FlagId:40002, FlagMnemonic:MPR, Action:review]
editsMap: [FlagId:50001, FlagMnemonic:CPT, Action:deny]
editsMap: [FlagId:60001, FlagMnemonic:DTU, Action:deny]
editsMap: [FlagId:70001, FlagMnemonic:ICD, Action:review]
editsMap: [FlagId:70002, FlagMnemonic:MPR, Action:review]
一旦我已填充我的地图,然后我需要能够以处理信息来寻找某些价值观。 我相信,我可以使用类似:
def thisValue = appliedEditsMap[FlagId, '10001'] ?: "default"
做一个快速查找。
有人可以帮助我了解如何编程值添加到Groovy的地图,而在地图已经覆盖值?
Answer 1:
你要像番石榴的多重映射 :
Multimap<String, String> myMultimap = ArrayListMultimap.create();
// Adding some key/value
myMultimap.put("Fruits", "Bannana");
myMultimap.put("Fruits", "Apple");
myMultimap.put("Fruits", "Pear");
myMultimap.put("Vegetables", "Carrot");
// Getting values
Collection<string> fruits = myMultimap.get("Fruits");
System.out.println(fruits); // [Bannana, Apple, Pear]
这家伙让Multimap之的纯Groovy的仿真:
class GroovyMultimap {
Map map = [:]
public boolean put(Object key, Object value) {
List list = map.get(key, [])
list.add(value)
map."$key" = list
}
}
您可以使用putAt
和getAt
在地图操作语法糖。 你也可以尝试混入在地图对象。
他还使用Groovy中使用番石榴的多重映射:
List properties = ['value1', 'value2', 'value3']
Multimap multimap = list.inject(LinkedListMultimap.create()) {
Multimap map, object ->
properties.each {
map.put(it, object."$it")
}
map
}
properties.each {
assertEquals (multimap.get(it), list."$it")
}
Answer 2:
我碰到这个几年前来到作为一个答案,在其他网站上类似的问题。 我找不到它最初来自因此,如果有人知道源请在这里发表它来了。
LinkedHashMap.metaClass.multiPut << { key, value ->
delegate[key] = delegate[key] ?: []; delegate[key] += value
}
def myMap = [:]
myMap.multiPut("a", "1")
myMap.multiPut("a", "2")
myMap.multiPut("a", "3")
myMap.each {key, list ->
println "${key} -> $value.list(",")
}
得到:
a -> 1,2,3
使用注射multiPut()方法确实神奇。
Answer 3:
你也可以做这样的事情:
// Dummy map for testing
lineEdits = [ flag:[
[id:10001, mnemonic:'TRA', action:'review'],
[id:10002, mnemonic:'REB', action:'deny'],
[id:10003, mnemonic:'UNB', action:'deny'],
[id:20001, mnemonic:'REB', action:'deny'],
[id:20002, mnemonic:'ICD', action:'review'],
[id:30001, mnemonic:'REB', action:'deny'],
[id:40001, mnemonic:'ICD', action:'review'],
[id:40002, mnemonic:'MPR', action:'review'],
[id:50001, mnemonic:'CPT', action:'deny'],
[id:60001, mnemonic:'DTU', action:'deny'],
[id:70001, mnemonic:'ICD', action:'review'],
[id:70002, mnemonic:'MPR', action:'review'] ] ]
def editsMap = lineEdits.flag
.groupBy { it.id } // Group by id
.collectEntries { k, v ->
[ k, v[ 0 ] ] // Just grab the first one (flatten)
}
assert editsMap[ 60001 ] == [ id:60001, mnemonic:'DTU', action:'deny' ]
Answer 4:
如果你想要做的事情多重映射无需外部类,你可以存储地图列表,而不是,语法也不会很麻烦或任何东西。
def editsMap = [:].withDefault{[]} lineEdits.flag.each { lineEdits_Flag -> editsMap.FlagId << lineEdits_Flag.id editsMap.FlagMnemonic << lineEdits_Flag.mnemonic editsMap.Action << lineEdits_Flag.action println "editsMap: ${editsMap}" }
或者,如果你真的首选原来的语法,它看起来像: editsMap.get('FlagId').add(lineEdits_Flag.id)
甚至可以这样: editsMap.get('FlagId') << lineEdits_Flag.id
这种解决方案的优势在于,它往往是比较明显的,你在做什么?比如它不是一个魔图是单品转换成一个列表(这不是标准地图的合同),但它始终是一个地图的,你只是作为一个地图列表的使用列表。
在不用彷徨总是工作描述的多重映射以同样的方式 - 它总是会返回列表中的映射项。
Answer 5:
地图是一组键 - 值映射关系,你在不同的值,通过插入钥匙,让你可以使用密钥后找到他们。 您的例子中值相同的密钥遍地堵塞。 你需要选择的唯一密钥。
使一些类来存储你的价值观在地图上一个条目:
class Stuff {
String flagMnemonic
String action
}
做一个地图,您将使用flagId作为关键(因为这是你如何识别标志唯一)和东西的价值(因为这是你想要查找的数据)。
def editsMap = [:]
如果您在此处使用类型声明,如果flagId是一个字符串,地图的类型将Map<String, Stuff>
。
现在你可以把东西放在地图:
lineEdits.flag.each { lineEdits_Flag ->
editsMap[lineEdits_Flag.id] =
new Stuff(
flagMnemonic: lineEdits_Flag.mnemonic,
action: lineEdits_Flag.action)
}
并把它背出来与
def myStuffFor10001 = editsMap['10001']
println myStuffFor10001.flagMnemonic // should equal 'TRA'
println myStuffFor10001.action // should equal 'review'
也有一个简单的替代使用?: "default"
设置默认值,你可以使用withDefault
创建地图时:
def defaultStuff = new Stuff(
flagMnemonic: "defaultMnemonic", action:"defaultAction")
def editsMap = [:].withDefault { defaultStuff }
所以,每当你从地图中不存在有问的东西,你指定的默认对象。
Answer 6:
为什么不使用像列表和关闭:
editsList = [
[FlagId:10001, FlagMnemonic:TRA, Action:review],
[FlagId:10002, FlagMnemonic:REB, Action:deny],
[FlagId:10003, FlagMnemonic:UNB, Action:deny],
[FlagId:20001, FlagMnemonic:REB, Action:deny],
[FlagId:20002, FlagMnemonic:ICD, Action:review],
[FlagId:30001, FlagMnemonic:REB, Action:deny],
[FlagId:40001, FlagMnemonic:ICD, Action:review],
[FlagId:40002, FlagMnemonic:MPR, Action:review],
[FlagId:50001, FlagMnemonic:CPT, Action:deny],
[FlagId:60001, FlagMnemonic:DTU, Action:deny],
[FlagId:70001, FlagMnemonic:ICD, Action:review],
[FlagId:70002, FlagMnemonic:MPR, Action:review]
]
def appliedEditsMap = {property,idValue->
return editsList.find{it[property] == idValue}
}
def thisValue = appliedEditsMap(FlagId, '10001') ?: "default"
Answer 7:
你需要把这个一类,然后添加类的地图。 从我看到你的信息涉及所以有一类存储是有道理的,除非我失去了什么
你可以做的是定义为类
class Flag {
String flagID
String flagMnemonic
String action
}
Now Put your Flag in to your map as
editsMap.put(10000,newFlag(flagID:'10000',flagMnemonic:'TES',action:'tes'))
文章来源: How do I add multiple Groovy map entries without overwriting the current entries?