首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java ArrayList of ArrayList

Java ArrayList of ArrayList
EN

Stack Overflow用户
提问于 2014-08-05 20:32:58
回答 4查看 110.4K关注 0票数 39

以下代码输出

代码语言:javascript
复制
[[100, 200, 300], [100, 200, 300]]. 

然而,我期望的是

代码语言:javascript
复制
[[100, 200, 300], [100, 200]], 

我哪里错了?

代码语言:javascript
复制
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);

}
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2014-08-05 20:33:45

您要向外部列表中添加两次对同一内部ArrayList的引用。因此,当您更改内部列表(通过添加300)时,您可以在“两个”内部列表中看到它(实际上只有一个内部列表,其中两个引用存储在外部列表中)。

要获得您想要的结果,您应该创建一个新的内部列表:

代码语言:javascript
复制
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);
}
票数 55
EN

Stack Overflow用户

发布于 2014-08-05 20:56:55

在阅读这个答案之前,您可能需要熟悉What is the difference between a variable, object, and reference?

这就是你现在拥有的

代码语言:javascript
复制
ArrayList<ArrayList<Integer>> outer = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> inner = new ArrayList<Integer>();        

会创造

代码语言:javascript
复制
outer -> []
inner -> []

它创建两个单独的列表,并将对它们的引用存储在变量outerinner中。

之后

代码语言:javascript
复制
inner.add(100);     
inner.add(200);

你的情况就像

代码语言:javascript
复制
outer -> []
inner -> [100, 200]

这是令人困惑的部分

代码语言:javascript
复制
outer.add(inner);
outer.add(inner);

在这里,inner变量的值(因此引用列表100,200)放置在outer列表中两次。这意味着outer“指向”100,200个列表两次。

代码语言:javascript
复制
//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看到这些更改,因为它们都是对同一个列表的引用。

所以如果我们用

代码语言:javascript
复制
outer.get(0).add(300);

outer.get(0)返回对相同列表的引用,因为inneradd(300)向该列表添加了新元素。这意味着在新的情况下

代码语言:javascript
复制
outer -> [ reference1 , reference2 ]
              |             |
      +-------+             |
      +---------------------+
      ↓
inner -> [100, 200, 300]

这就是为什么当你打印outer时你看到的

代码语言:javascript
复制
[[100, 200, 300], [100, 200, 300]]. 
 ^^^^^^^^^^^^^^^  ^^^^^^^^^^^^^^^
   from get(0)      from get(1)

您真正需要的是创建单独的列表,这样reference1reference2就可以指向两个单独的列表。有点像

代码语言:javascript
复制
outer  -> []
inner1 -> [100, 200]
inner2 -> [100, 200]

以后会被组织成

代码语言:javascript
复制
outer -> [ reference1 , reference2 ]
              |             |
       +------+             |
       ↓                    |
inner1 -> [100, 200]        |
                            |
       +--------------------+
       ↓
inner2 -> [100, 200]

你可以这样做

代码语言:javascript
复制
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]]
票数 51
EN

Stack Overflow用户

发布于 2014-08-05 20:34:40

命令outer.add(inner)添加对inner的引用,而不是它的副本。

因此,当您将两个对inner的引用添加到ArrayList outer时,您将添加两个相同的内容。通过inner修改outer.get(0)也会修改outer.get(1)中的值,因为它们引用的是相同的内容。

如果您创建一个inner的副本并使用它,那么您将有两个不同的实例,并且能够分别修改它们。您可以使用一个简单的命令来完成这个任务:

代码语言:javascript
复制
outer.add(new ArrayList<[var type]>(inner));

new ArrayList(inner)的指令创建了一个新的ArrayList,其中包含了inner的内容,但是没有使用与inner相同的实例。因此,您将保留内容,但不保留重复引用。

通过添加新副本而不是引用,您可以修改副本而不修改您可能称之为“原件”的内容。

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25147799

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档