以下代码输出
[[100, 200, 300], [100, 200, 300]].
Run Code Online (Sandbox Code Playgroud)
但是,我的期望是
[[100, 200, 300], [100, 200]],
Run Code Online (Sandbox Code Playgroud)
我哪里错了?
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);
}
Run Code Online (Sandbox Code Playgroud)
Era*_*ran 47
您将同一内部的引用添加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);
}
Run Code Online (Sandbox Code Playgroud)
Psh*_*emo 39
这就是你现在拥有的
ArrayList<ArrayList<Integer>> outer = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> inner = new ArrayList<Integer>();
Run Code Online (Sandbox Code Playgroud)
将创造
outer -> []
inner -> []
Run Code Online (Sandbox Code Playgroud)
后
inner.add(100);
inner.add(200);
Run Code Online (Sandbox Code Playgroud)
你的情况看起来像
outer -> []
inner -> [100, 200]
Run Code Online (Sandbox Code Playgroud)
这里有令人困惑的部分
outer.add(inner);
outer.add(inner);
Run Code Online (Sandbox Code Playgroud)
实际上复制了inner引用值,这意味着它们指向相同的列表inner
outer -> [ reference1 , reference2 ]
| |
+-------+ |
+---------------------+
?
inner +-> [100, 200]
Run Code Online (Sandbox Code Playgroud)
这意味着如果您更改了inner您所持有的列表状态,则可以使用reference1和查看这些更改reference2.如果您通过其他引用更改此列表,则相同,因此在您使用时
outer.get(0).add(300);
Run Code Online (Sandbox Code Playgroud)
get(0)返回列表,您也可以通过inner或get(1)添加新元素访问,所以现在情况看起来像
outer -> [ reference1 , reference2 ]
| |
+-------+ |
+---------------------+
?
inner -> [100, 200, 300]
Run Code Online (Sandbox Code Playgroud)
这就是为什么当你打印outer你看到的时候
[[100, 200, 300], [100, 200, 300]].
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
from get(0) from get(1)
Run Code Online (Sandbox Code Playgroud)
你真正需要的是创建单独的列表,reference1并reference2指向两个单独的列表.所以你需要类似的东西
outer -> []
inner1 -> [100, 200]
inner2 -> [100, 200]
Run Code Online (Sandbox Code Playgroud)
这将在以后组织
outer -> [ reference1 , reference2 ]
| |
+------+ |
? |
inner1 -> [100, 200] |
|
+--------------------+
?
inner2 -> [100, 200]
Run Code Online (Sandbox Code Playgroud)
你可以这样做
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);
Run Code Online (Sandbox Code Playgroud)
Aza*_*Aza 10
该命令outer.add(inner)添加一个引用到inner,不是它的一个副本.
所以,当你添加两个引用inner到ArrayList outer,你把两个同样的事情.修改inner通过outer.get(0)还修改的值outer.get(1),因为它们指的是同一件事.
如果您创建了一个副本inner并使用它,那么您将拥有两个不同的实例,并且可以单独修改它们.您可以使用简单的命令执行此操作:
outer.add(new ArrayList<[var type]>(inner));
Run Code Online (Sandbox Code Playgroud)
用于new ArrayList(inner)创建具有内部内容的新 指令- 但不使用相同的实例.因此,您将保留内容,但不保留重复的引用.ArrayListinnerinner
通过添加新副本而不是引用,您可以修改副本而无需修改可能称为"原始"的副本.