ArrayList的Java ArrayList

以下代码输出

[[100, 200, 300], [100, 200, 300]]. 

但是,我的期望是

 [[100, 200, 300], [100, 200]], 

我哪里错了?

 public static void main(String[] args) { ArrayList<ArrayList> outer = new ArrayList<ArrayList>(); ArrayList inner = new ArrayList(); inner.add(100); inner.add(200); outer.add(inner); outer.add(inner); outer.get(0).add(300); System.out.println(outer); } 

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

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

 public static void main(String[] args) { ArrayList> outer = new ArrayList>(); ArrayList inner = new ArrayList(); inner.add(100); inner.add(200); outer.add(inner); // add first list inner = new ArrayList(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); } 

这就是你现在拥有的

 ArrayList> outer = new ArrayList>(); ArrayList inner = new ArrayList(); 

将创造

 outer -> [] inner -> [] 

 inner.add(100); inner.add(200); 

你的情况看起来像

 outer -> [] inner -> [100, 200] 

这里有令人困惑的部分

 outer.add(inner); outer.add(inner); 

实际上复制了inner引用的值,这意味着它们从inner指向相同的列表

 outer -> [ reference1 , reference2 ] | | +-------+ | +---------------------+ ↓ inner +-> [100, 200] 

这意味着如果您更改inner持有的列表状态,您将能够使用reference1reference2查看这些更改。 如果您通过其他引用更改此列表,则相同,因此在您使用时

 outer.get(0).add(300); 

get(0)返回你也可以通过innerget(1)访问的列表并添加新元素,所以现在情况看起来像

 outer -> [ reference1 , reference2 ] | | +-------+ | +---------------------+ ↓ inner -> [100, 200, 300] 

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

 [[100, 200, 300], [100, 200, 300]]. ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ from get(0) from get(1) 

您实际需要的是创建单独的列表,以便reference1reference2指向两个单独的列表。 所以你需要类似的东西

 outer -> [] inner1 -> [100, 200] inner2 -> [100, 200] 

这将在以后组织

 outer -> [ reference1 , reference2 ] | | +------+ | ↓ | inner1 -> [100, 200] | | +--------------------+ ↓ inner2 -> [100, 200] 

你可以这样做

 List> outer = new ArrayList>(); List inner1 = new ArrayList(); List inner2 = new ArrayList(); 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); 

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

因此,当您向ArrayList outer添加两个inner引用时,您将添加两个相同的内容。 修改innerouter.get(0)也会修改outer.get(1)的值,因为它们引用相同的东西。

如果你创建了一个inner副本并使用它,那么你将有两个不同的实例,并能够单独修改它们。 您可以使用一个简单的命令执行此操作:

 outer.add(new ArrayList<[var type]>(inner)); 

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

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