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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 23:43:11  来源:igfitidea点击:

Java ArrayList of ArrayList

javaarraylist

提问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 ArrayListtwice 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 innerto the ArrayList outer, you're adding two of the same thing. Modifying innerthrough outer.get(0)also modifies the value in outer.get(1), because they refer to the same thing.

所以,当你添加两个引用innerArrayList outer,你把两个同样的事情。修改innerthroughouter.get(0)也会修改 中的值outer.get(1),因为它们指的是同一个东西。

If you create a copy of innerand 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 newArrayListwith the contents of innerinside 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 innerreference 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 inneryou will be able to see these changes using reference1and 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 inneror 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 outeryou 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 reference1and reference2will point to two separate lists. So you need something like

你真正需要的是创建单独的列表,reference1reference2会指向两个单独的列表。所以你需要类似的东西

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);