5

我想执行一个副本并获得两个不同的对象,这样我就可以在不影响原件的情况下处理副本。

我有这个代码(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]]

这是怎么回事 ?

4

2 回答 2

5

只需调用b = a集合b作为列表的相同实例(包含相同的列表实例)a

使用方法 b 调用第二种方法a.each { b.add(it) }指向不同的 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

(确实,你们当中的细心的人会注意到sort不需要false传递给它,因为我们已经有了一个新实例,多亏了unique

于 2012-11-09T10:22:35.347 回答
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]'
于 2012-11-10T05:35:24.327 回答