在阅读本答案之前,您可能需要了解变量、对象和引用之间的区别是什么?
这就是您现在拥有的内容。
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]
这意味着如果您更改列表 [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);
outer.add(new ArrayList<String>(inner));
。这行代码的意思是将内部List
的内容复制到一个新的ArrayList
中,然后将其添加到外部List
中。 - Keppil