ArrayList的Java ArrayList

Jie*_*Jie 30 java arraylist

以下代码输出

[[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)返回列表,您也可以通过innerget(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)

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

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)

  • 视觉效果就是一切 (6认同)

Aza*_*Aza 10

该命令outer.add(inner)添加一个引用inner,不是它的一个副本.

所以,当你添加两个引用innerArrayList 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

通过添加新副本而不是引用,您可以修改副本而无需修改可能称为"原始"的副本.