添加后清除一些内容,ArrayList也会清除ArrayList

时间:2017-11-24 17:33:36

标签: java arraylist

我有一个包含Arraylists的ArrayList,这是代码:

ArrayList<ArrayList<String>> results = new ArrayList<ArrayList<String>>();
ArrayList<String> row = new ArrayList<String>();

我想要的是results ArrayList包含row ArrayList。我认为在向ArrayList添加内容之后,它将被硬编码到该ArrayList中。但是看起来ArrayList的内容仍然与我添加到它的变量的内容有关,因为当我运行这段代码时:

row.add("ROW 1 ITEM 1");
row.add("ROW 1 ITEM 2");
row.add("ROW 1 ITEM 3");
row.add("ROW 1 ITEM 4");
row.add("ROW 1 ITEM 5");
row.add("ROW 1 ITEM 6");
results.add(row);
row.clear();
log(results.toString());

控制台中记录的结果是[[]]。我有什么方法可以这样使用它吗?

6 个答案:

答案 0 :(得分:2)

是的,Java使用引用。如果您在引用clear的引用上调用ArrayList,则引用完全相同内存的其他引用将看到相同的内容。 ArrayList为空。

如果要保留内容,请将其保存到其他ArrayList实例。

答案 1 :(得分:2)

这是因为Java使用引用而不是复杂数据类型的克隆/副本(非复杂类型为intchar和类似)。

在你的情况下,这意味着ArrayList<String> row在内存中获得一些位置并存储在那里 如果您现在通过row直接将result添加到result.add(row);,只需在内存中row的原始位置添加引用(或C ++中的指针)ArrayList result }。

所以这意味着如果您更改row中的任何内容,它也会在result中更改,因为两个对象都会在内存中引用相同的位置并进行修改。

要解决此问题,每次要添加row副本时都必须创建一个新副本,该副本引用内存中的其他位置,然后将副本添加到结果中。
1.方式:
创建一个这样的方法:

ArrayList<String> createCopy (ArrayList<String> orginal) {
  ArrayList<String> copy = new ArrayList<String>()
  for (String s:orginal) {
    copy.add(s);
  }
  return copy;
}

2。方法:
查找您最喜欢的方法如何在java中创建ojbects的深层克隆/副本并使用它。

答案 2 :(得分:1)

您正在将ArrayList行的引用添加到结果中。一旦调用row.clear(),将删除所有元素。您可以在清除之前记录,或者不添加引用创建新的ArrayList并深度复制列表。

答案 3 :(得分:0)

是的,这不起作用,因为您在打印之前删除行ArrayList。除非您将内容复制到结果ArrayList,否则将删除该数据,因为我相信在调用.toString()方法时引用了行ArrayList

答案 4 :(得分:0)

那是因为数组列表中的内容aréobject'a引用,所以你有两个引用指向行,一个是变量行,另一个引用是数组结果的第一个元素,如果你改变了对象使用行引用(变量),它将影响arraylist结果中的arraylist

答案 5 :(得分:0)

您可以根据内存如何分配给Java中的对象来理解这一点。

最初,您只有一个 row Arraylist,并且您将该ArrayList添加到 results Arraylist。

您需要了解这一点,实例化/分配内存只有一个 row 的ArrayList,以及 results ArrayList仅包含 row 对象, NOT 任何新对象。

因此,当您删除 row 时,该对象将被删除。

由于内存中只有一个对象,删除后输出为空。