我有一个ArrayList<ArrayList<Integer>> res
whic包含一些整数子集。我保留在ArrayList<ArrayList<Integer>> prev
中的部分子集。例如res = [[1], [1, 2], [2]]
和prev = [[1, 2], [2]]
。然后,我想创建新的ArrayList<ArrayList<Integer>> tmp
,它是prev
的副本,以便在tmp
的每个子集中添加新元素,而无需更改prev
和然后将tmp
添加到结果中。我使用的代码如下:
ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
ArrayList<ArrayList<Integer>> prev = new ArrayList<ArrayList<Integer>>();
for (int i = 0; i < S.length; i++) {
ArrayList<ArrayList<Integer>> tmp = new ArrayList<ArrayList<Integer>>();
if(something){
tmp = new ArrayList<ArrayList<Integer>>(prev);
for(ArrayList<Integer> a: tmp){
a.add(S[i]);
}
res.addAll(tmp);
prev = new ArrayList<ArrayList<Integer>>(tmp);
}
因此,如果res = [[1], [1, 2], [2]]
和prev = [[1, 2], [2]]
S[i] = 2
我希望tmp成为[[1, 2, 2], [2, 2]]
,然后将tmp
添加到res
。问题是,当我向tmp
添加元素时,我也会更改prev
,我也会更改res
,这是我不想要的。因此,在上述迭代之后,我的res
包含[[1], [1, 2, 2], [2, 2], [1, 2, 2], [2, 2]]
而不是[[1], [1, 2], [2], [1, 2, 2], [2, 2]]
。我尝试使用tmp = new ArrayList<ArrayList<Integer>>(prev);
更改此行tmp.addAll(prev);
,但它再次无效。我的错误在哪里?
修改
我想我解决了这个问题 - 我将行tmp = new ArrayList<ArrayList<Integer>>(prev);
更改为
for(ArrayList<Integer> a: prev){
tmp.add(new ArrayList<Integer>(a));
}
但是,我仍然需要一个表达式,为什么这个有效,为什么以前不起作用?
答案 0 :(得分:0)
问题是您正在更改原始列表值(通过引用传递它们)
我认为您必须使用clone()
来避免副作用。
代码应该是:
ArrayList<ArrayList<Integer>> prev = new ArrayList<ArrayList<Integer>>();
for (int i = 0; i < SCloned.length; i++) {
ArrayList<ArrayList<Integer>> SCloned = (ArrayList<ArrayList<Integer>>)S.clone();
ArrayList<ArrayList<Integer>> tmp = new ArrayList<ArrayList<Integer>>();
然后执行a.add(SCloned[i]);
( UNTESTED )
答案 1 :(得分:0)
tmp = new ArrayList<ArrayList<Integer>>(prev)
这会创建一个浅副本,这是一个新的顶级ArrayList
,其中包含与原始相同的引用。 tmp
的成员引用了仍在prev
中的完全相同的对象。
您需要制作整个结构的深副本,这是您通过编辑完成的。
请注意Integer
个对象是不可变的。因此,可以从多个地方引用它们,因此它们不需要复制。