我们正在尝试迭代Map
,但没有任何成功。我们将问题简化为这个最小的例子:
def map = [
'monday': 'mon',
'tuesday': 'tue',
]
如果我们尝试迭代:
map.each{ k, v -> println "${k}:${v}" }
仅输出第一个条目:monday:mon
我们所知道的替代方案甚至无法进入循环:
for (e in map)
{
println "key = ${e.key}, value = ${e.value}"
}
或
for (Map.Entry<String, String> e: map.entrySet())
{
println "key = ${e.key}, value = ${e.value}"
}
失败,两者都只显示异常java.io.NotSerializableException: java.util.LinkedHashMap$Entry
。 (这可能与提出“真实”异常时发生的异常有关,阻止我们知道发生了什么)。
截至今天(2016/10/20),我们正在使用最新的稳定jenkins(2.19.1),所有插件都是最新的。
是否有解决方案在Jenkins管道Groovy脚本中迭代Map
中的元素?
答案 0 :(得分:19)
自从我玩这个游戏以来已经过了一段时间,但迭代地图(和其他容器)的最好方法是使用“经典”for循环,或者“for in”。见Bug: Mishandling of binary methods accepting Closure
对于您的具体问题,大多数(所有?)管道DSL命令将添加一个序列点,我的意思是它可以保存管道状态并在以后恢复它。可以考虑等待用户输入,例如,即使重启也要保持此状态。 结果是每个实例都必须被序列化 - 但遗憾的是,标准的Map迭代器不可序列化。 Original Thread
我能想出的最佳解决方案是定义一个函数,将Map转换为可序列化的MapEntries列表。该函数没有使用任何管道步骤,因此不必在其中进行任何序列化。
@NonCPS
def mapToList(depmap) {
def dlist = []
for (def entry2 in depmap) {
dlist.add(new java.util.AbstractMap.SimpleImmutableEntry(entry2.key, entry2.value))
}
dlist
}
显然需要为每个要迭代的地图调用它,但是它的优点是循环体保持不变。
for (def e in mapToList(map))
{
println "key = ${e.key}, value = ${e.value}"
}
您必须第一次批准SimpleImmutableEntry
构造函数,或者很可能通过将mapToList函数放在工作流库中来解决这个问题。
答案 1 :(得分:0)
或更简单
for (def key in map.keySet()) {
println "key = ${key}, value = ${map[key]}"
}