以下代码输出
[[100, 200, 300], [100, 200, 300]]. 然而,我期望的是
[[100, 200, 300], [100, 200]], 我哪里错了?
public static void main(String[] args) {
ArrayList<ArrayList<Integer>> outer = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> inner = new ArrayList<Integer>();
inner.add(100);
inner.add(200);
outer.add(inner);
outer.add(inner);
outer.get(0).add(300);
System.out.println(outer);
}发布于 2014-08-05 20:33:45
您要向外部列表中添加两次对同一内部ArrayList的引用。因此,当您更改内部列表(通过添加300)时,您可以在“两个”内部列表中看到它(实际上只有一个内部列表,其中两个引用存储在外部列表中)。
要获得您想要的结果,您应该创建一个新的内部列表:
public static void main(String[] args) {
ArrayList<ArrayList<Integer>> outer = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> inner = new ArrayList<Integer>();
inner.add(100);
inner.add(200);
outer.add(inner); // add first list
inner = new ArrayList<Integer>(inner); // create a new inner list that has the same content as
// the original inner list
outer.add(inner); // add second list
outer.get(0).add(300); // changes only the first inner list
System.out.println(outer);
}发布于 2014-08-05 20:56:55
在阅读这个答案之前,您可能需要熟悉What is the difference between a variable, object, and reference?
这就是你现在拥有的
ArrayList<ArrayList<Integer>> outer = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> inner = new ArrayList<Integer>(); 会创造
outer -> []
inner -> []它创建两个单独的列表,并将对它们的引用存储在变量outer和inner中。
之后
inner.add(100);
inner.add(200);你的情况就像
outer -> []
inner -> [100, 200]这是令人困惑的部分
outer.add(inner);
outer.add(inner);在这里,inner变量的值(因此引用列表100,200)放置在outer列表中两次。这意味着outer“指向”100,200个列表两次。
//note: `reference1` == `reference2` (like 42 == 42) since they point to same object
outer -> [ reference1, reference2 ]
| |
+-------+ |
+---------------------+
↓
inner +-> [100, 200]这意味着,如果您更改list 100,200的状态,您将能够使用outer.get(0)、outer.get(1)或inner看到这些更改,因为它们都是对同一个列表的引用。
所以如果我们用
outer.get(0).add(300);outer.get(0)返回对相同列表的引用,因为inner和add(300)向该列表添加了新元素。这意味着在新的情况下
outer -> [ reference1 , reference2 ]
| |
+-------+ |
+---------------------+
↓
inner -> [100, 200, 300]这就是为什么当你打印outer时你看到的
[[100, 200, 300], [100, 200, 300]].
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
from get(0) from get(1)您真正需要的是创建单独的列表,这样reference1和reference2就可以指向两个单独的列表。有点像
outer -> []
inner1 -> [100, 200]
inner2 -> [100, 200]以后会被组织成
outer -> [ reference1 , reference2 ]
| |
+------+ |
↓ |
inner1 -> [100, 200] |
|
+--------------------+
↓
inner2 -> [100, 200]你可以这样做
List<List<Integer>> outer = new ArrayList<List<Integer>>();
List<Integer> inner1 = new ArrayList<Integer>();
List<Integer> inner2 = new ArrayList<Integer>();
inner1.add(100);
inner1.add(200);
inner2.add(100);
inner2.add(200);
outer.add(inner1);
outer.add(inner2);
outer.get(0).add(300);
System.out.println(outer);
//Output: [[100, 200, 300], [100, 200]]发布于 2014-08-05 20:34:40
命令outer.add(inner)添加对inner的引用,而不是它的副本。
因此,当您将两个对inner的引用添加到ArrayList outer时,您将添加两个相同的内容。通过inner修改outer.get(0)也会修改outer.get(1)中的值,因为它们引用的是相同的内容。
如果您创建一个inner的副本并使用它,那么您将有两个不同的实例,并且能够分别修改它们。您可以使用一个简单的命令来完成这个任务:
outer.add(new ArrayList<[var type]>(inner));new ArrayList(inner)的指令创建了一个新的ArrayList,其中包含了inner的内容,但是没有使用与inner相同的实例。因此,您将保留内容,但不保留重复引用。
通过添加新副本而不是引用,您可以修改副本而不修改您可能称之为“原件”的内容。
https://stackoverflow.com/questions/25147799
复制相似问题