1

我有一个数组列表,看起来像:

private ArrayList<ArrayList<Integer>> matrix = new ArrayList<ArrayList<Integer>>(9);

它充满了这些元素:

[[7], [1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 5, 6, 7, 8, 9], [3], [1, 2, 3, 4, 5, 6, 7, 8, 9], [4], [1, 2, 3, 4, 5, 6, 7, 8, 9], [9]]

现在我想从第二个索引中删除“1”,所以我想要的输出是:

[[7], [2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 5, 6, 7, 8, 9], [3], [1, 2, 3, 4, 5, 6, 7, 8, 9], [4], [1, 2, 3, 4, 5, 6, 7, 8, 9], [9]]

但是当我在表单中使用 remove 方法时:

matrix.get(1).remove(0);

输出是:

[[7], [2, 3, 4, 5, 6, 7, 8, 9], [2, 3, 4, 5, 6, 7, 8, 9], [2, 3, 4, 5, 6, 7, 8, 9], [3], [2, 3, 4, 5, 6, 7, 8, 9], [4], [2, 3, 4, 5, 6, 7, 8, 9], [9]]

您可以看到主 ArrayList 的所有 ArrayLists 中的每个“1”都被删除,而不是仅在第二个索引处。如何更改我的代码,以便只删除第二个索引的“1”?

4

3 回答 3

2

这是因为您将相同的ArrayList实例存储在 external 中ArrayList

outerList = [instance1, instance2, instance2, instance2, ...]

当您从 instance2 中删除第一个元素时,所有其他索引中都可以看到更改。

如果您想避免这些问题,您应该为每个子列表创建新实例并从原始列表中复制元素。

于 2014-03-14T11:26:19.273 回答
2

可能matrix包含对相同内容的多个引用ArrayList(包含 [1, 2, 3, 4, 5, 6, 7, 8, 9])。

于 2014-03-14T11:26:30.740 回答
0

您在这里遇到了引用和实例之间的区别。

当您将 child ArrayLists 添加到第一个中时,您实际上所做的是将引用存储到列表中,然后该引用指向一个ArrayList.

请注意,对于ArrayList指定了正确类型的(例如ArrayList<?>)将其自身的引用插入到列表中,它甚至是合法的(但绝对不推荐)!

如果您ArrayList多次存储相同的内容,那么它将复制并创建多个引用,但这些引用仍将指向同一个Object

您需要创建一个新的ArrayList(使用new或类似的东西clone()来创建孩子ArrayLists,然后将新列表添加到原始列表中。

于 2014-03-14T11:30:38.473 回答