我想执行一个副本并获取两个不同的对象,这样我就可以在不影响原件的情况下处理副本。
我有这段代码(groovy 2.0.5):
def a = [[1,5,2,1,1], ["one", "five", "two", "one", "one"]]
def b = a
b.add([6,6,6,6,6,6])
println a
println b
产生:
[[1, 5, 2, 1, 1], [one, five, two, one, one], [6, 6, 6, 6, 6, 6]]
[[1, 5, 2, 1, 1], [one, five, two, one, one], [6, 6, 6, 6, 6, 6]]
似乎b和a实际上是同一个对象
我可以用这种方式修复它:
def a = [[1,5,2,1,1], ["one", "five", "two", "one", "one"]]
def b = []
a.each {
b.add(it)
}
b.add([6,6,6,6,6])
println a
println b
产生我想要的结果:
[[1, 5, 2, 1, 1], [one, five, two, one, one]]
[[1, 5, 2, 1, 1], [one, five, two, one, one], [6, 6, 6, 6, 6]]
但是现在看看这个,我想要原始对象和具有唯一和有序元素的副本:
def a = [[1,5,2,1,1], ["one", "five", "two", "one", "one"]]
def b = a
b.each {
it.unique().sort()
}
println a
println b
产生:
[[1, 2, 5], [five, one, two]]
[[1, 2, 5], [five, one, two]]
如果我这次尝试相同的修复它不起作用:
def a = [[1,5,2,1,1], ["one", "five", "two", "one", "one"]]
def b = []
a.each {
b.add(it)
}
b.each {
it.unique().sort()
}
println a
println b
仍然产生:
[[1, 2, 5], [five, one, two]]
[[1, 2, 5], [five, one, two]]
发生了什么事?
答案 0 :(得分:5)
只需调用b = a
将b
设置为与a
使用a.each { b.add(it) }
调用第二个方法意味着b指向不同的List实例,但b
的内容与a
您需要的是:
def b = a*.collect()
b.each {
it.unique().sort()
}
因此a*.collect()
为a
您也可以在一行中执行此操作:
def b = a*.unique( false )*.sort( false )
将false
传递给unique
和sort
stop those method changing the original lists,并强制他们返回新的列表实例。
(事实上你们中间的观察者会注意到sort
不需要false
传递给它,因为unique
已经有了一个新的实例)子>
答案 1 :(得分:2)
Groovy有Collection#collectNested
,这是#collect
的递归形式。这将创建任意深度列表的副本。在1.8.1版之前,它被称为#collectAll
。
final a = [
'a', [ 'aa', 'ab', [ 'aba', 'abb', 'abc' ], 'ac', 'ad' ], 'b', 'c', 'd', 'e'
]
final b = a.collectNested { it }
b[0] = 'B'
final c = a.collectNested { it * 2 }
c[0] = 'C'
assert a as String ==
'[a, [aa, ab, [aba, abb, abc], ac, ad], b, c, d, e]'
assert b as String ==
'[B, [aa, ab, [aba, abb, abc], ac, ad], b, c, d, e]'
assert c as String ==
'[C, [aaaa, abab, [abaaba, abbabb, abcabc], acac, adad], bb, cc, dd, ee]'