java如何从旧的ArrayList<ArrayList<Integer>>创建新的ArrayList而不更改旧的?
我有一个ArrayList<ArrayList<Integer>> res
,它包含一些整数子集。这些子集的一部分我保存在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]]
{[[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.addAll(prev);
更改这一行tmp = new ArrayList<ArrayList<Integer>>(prev);
,但它没有再起作用。我的错在哪里
编辑:
我想我解决了这个问题——我把tmp = new ArrayList<ArrayList<Integer>>(prev);
行改为
for(ArrayList<Integer> a: prev){
tmp.add(new ArrayList<Integer>(a));
}
然而,我仍然需要解释一下为什么这样做有效,以及为什么之前的方法不起作用
# 1 楼答案
问题是您正在更改原始列表值(通过引用传递) 我认为你必须使用
clone()
来避免副作用代码应该是这样的:
然后做
a.add(SCloned[i]);
(未经测试)# 2 楼答案
这将创建一个浅副本,它是一个新的顶级
ArrayList
,包含与原始版本相同的引用。tmp
的成员是对仍然在prev
中的完全相同对象的引用你需要对整个结构进行深度复制,这是你通过编辑完成的
注意
Integer
对象是不可变的。因此,可以从多个地方引用它们,因此它们不需要重复