如何创建新的ArrayList <arraylist <integer>&gt;从一个旧的,而不改变旧的?</arraylist <整数>

时间:2014-08-25 00:55:28

标签: java list reference

我有一个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));
}

但是,我仍然需要一个表达式,为什么这个有效,为什么以前不起作用?

2 个答案:

答案 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个对象是不可变的。因此,可以从多个地方引用它们,因此它们不需要复制。