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
持有的列表状态,您将能够使用reference1
和reference2
查看这些更改。 如果您通过其他引用更改此列表,则相同,因此在您使用时
outer.get(0).add(300);
get(0)
返回你也可以通过inner
或get(1)
访问的列表并添加新元素,所以现在情况看起来像
outer -> [ reference1 , reference2 ] | | +-------+ | +---------------------+ ↓ inner -> [100, 200, 300]
这就是为什么当你在outer
打印时你会看到的
[[100, 200, 300], [100, 200, 300]]. ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ from get(0) from get(1)
您实际需要的是创建单独的列表,以便reference1
和reference2
指向两个单独的列表。 所以你需要类似的东西
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
引用时,您将添加两个相同的内容。 修改inner
到outer.get(0)
也会修改outer.get(1)
的值,因为它们引用相同的东西。
如果你创建了一个inner
副本并使用它,那么你将有两个不同的实例,并能够单独修改它们。 您可以使用一个简单的命令执行此操作:
outer.add(new ArrayList<[var type]>(inner));
new ArrayList(inner)
的指令创建一个新的 ArrayList
,其中包含inner
的内容 – 但不使用与inner
相同的实例。 因此,您将保留内容,但不保留重复的引用。
通过添加新副本而不是引用,您可以修改副本而无需修改可能称为“原始”的副本。