Java ArrayList 的 ArrayList
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25147799/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java ArrayList of ArrayList
提问by Jie
The following code outputs
以下代码输出
[[100, 200, 300], [100, 200, 300]].
However, what I expect is
然而,我期望的是
[[100, 200, 300], [100, 200]],
Where am I wrong?
我哪里错了?
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);
}
采纳答案by Eran
You are adding a reference to the same inner ArrayList
twice to the outer list. Therefore, when you are changing the inner list (by adding 300), you see it in "both" inner lists (when actually there's just one inner list for which two references are stored in the outer list).
您正在ArrayList
两次向外部列表添加对同一内部的引用。因此,当您更改内部列表(通过添加 300)时,您会在“两个”内部列表中看到它(实际上只有一个内部列表,其两个引用存储在外部列表中)。
To get your desired result, you should create a new inner list :
为了得到你想要的结果,你应该创建一个新的内部列表:
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);
}
回答by Eran
The command outer.add(inner)
adds a referenceto inner
, not a copy of it.
该命令outer.add(inner)
添加一个引用到inner
,不是它的一个副本。
So, when you add two references to inner
to the ArrayList outer
, you're adding two of the same thing. Modifying inner
through outer.get(0)
also modifies the value in outer.get(1)
, because they refer to the same thing.
所以,当你添加两个引用inner
到ArrayList outer
,你把两个同样的事情。修改inner
throughouter.get(0)
也会修改 中的值outer.get(1)
,因为它们指的是同一个东西。
If you create a copy of inner
and use that instead, then you'll have two different instances and be able to modify them separately. You can do this with a simple command:
如果您创建一个副本inner
并改为使用它,那么您将拥有两个不同的实例并且能够分别修改它们。你可以用一个简单的命令来做到这一点:
outer.add(new ArrayList<[var type]>(inner));
The instruction for new ArrayList(inner)
creates a newArrayList
with the contents of inner
inside of it - but doesn't use the same instance as inner
. Thus, you'll retain the content, but not retain the duplicated reference.
指令new ArrayList(inner)
创建一个新的,ArrayList
其中的内容inner
- 但不使用与inner
. 因此,您将保留内容,但不会保留重复的引用。
By adding the new copy instead of the reference, you can modify the copy without modifying what you might call the "original."
通过添加新副本而不是引用,您可以修改副本而无需修改您可能称之为“原始”的内容。
回答by Pshemo
This is what you have now
这就是你现在拥有的
ArrayList<ArrayList<Integer>> outer = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> inner = new ArrayList<Integer>();
will create
会创造
outer -> []
inner -> []
After
后
inner.add(100);
inner.add(200);
your situation looks like
你的情况看起来像
outer -> []
inner -> [100, 200]
Here comes confusing part
令人困惑的部分来了
outer.add(inner);
outer.add(inner);
which in fact copy value of inner
reference which means they point to same list from inner
这实际上复制了inner
引用的值,这意味着它们指向相同的列表inner
outer -> [ reference1 , reference2 ]
| |
+-------+ |
+---------------------+
↓
inner +-> [100, 200]
which means that if you change state of list held by inner
you will be able to see these changes using reference1
and reference2
. Same if you change this list via other references, so when you use
这意味着如果您更改持有的列表的状态,inner
您将能够使用reference1
和看到这些更改reference2
。如果您通过其他参考更改此列表,则相同,因此当您使用
outer.get(0).add(300);
get(0)
returns list which you can access also via inner
or get(1)
and adding new element so now situation looks like
get(0)
返回列表,您也可以通过inner
或访问该列表get(1)
并添加新元素,所以现在情况看起来像
outer -> [ reference1 , reference2 ]
| |
+-------+ |
+---------------------+
↓
inner -> [100, 200, 300]
That is why when you print outer
you are seeing
这就是为什么当您打印时outer
您会看到
[[100, 200, 300], [100, 200, 300]].
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
from get(0) from get(1)
What you actually need is to create separate list so reference1
and reference2
will point to two separate lists. So you need something like
你真正需要的是创建单独的列表,reference1
并reference2
会指向两个单独的列表。所以你需要类似的东西
outer -> []
inner1 -> [100, 200]
inner2 -> [100, 200]
which will be later organized to
稍后将组织到
outer -> [ reference1 , reference2 ]
| |
+------+ |
↓ |
inner1 -> [100, 200] |
|
+--------------------+
↓
inner2 -> [100, 200]
You can do it this way
你可以这样做
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);
回答by Vayuj Rajan
Try this example in IDE:
在 IDE 中试试这个例子:
ArrayList<ArrayList<String>> ext = new ArrayList<ArrayList<String>>();
String[] arr = {"1","2","3","4","5","6"};
int n=arr.length;
for(int i=0;i<n;i++){
ArrayList temp = new ArrayList<String>();
for(int j=i;j<n;j++){
temp.add(arr[j]);
// this the line that needs to look at. Rather than pointing to the same memory reference creating a new ArrayList will store it in a different memory location. If you just add temp then it will point to same memory location.
ext.add(new ArrayList<String>(temp));
// Comment above line and uncomment below to see the difference
//ext.add(temp);
}
}
System.out.println(ext);