关于java:ArrayList< ArrayList>>

ArrayList<ArrayList>> is backedup by the ArrayList that is being added

我正在创建一个ArrayListArrayList,并添加ArrayLists。但每次我对ArrayList进行更改时,它都会反映在ArrayList中。

例子:

1
2
3
4
5
6
7
List<List<String>> list1 = new ArrayList<>();
List<String> list2 = new ArrayList<String>();
list2.add("Cat");
list1.add(list2);  //no problem
list2.clear();
list2.add("Dog");
list1.add(list2);  //problem! the cat is replaced by two dogs this time!!

如何确保list2的更新不反映在list1中?


简短回答…代替

1
list2.clear();

具有

1
list2 = new ArrayList<String>();

这是因为list1.add(list2)list1中增加了对list2的引用。它没有复制list2所指的清单。因此,您最终将多个对同一列表对象的引用添加到list1

这是Java参数传递方式的结果,以及集合API都被设计为工作的方式。


我从以下同等但可运行的程序中观察到的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import java.util.List;
import java.util.ArrayList;

public class Test1 {


    public static void main(String[] args){

        List<ArrayList<String>> list1 = new ArrayList<ArrayList<String>>();    
        ArrayList<String> list2 = new ArrayList<String>();

        list2.add("Cat");
        System.out.println(list2);

        list1.add(list2);
        System.out.println(list1);

        list2.clear();
        System.out.println(list2);

        list2.add("Dog");
        System.out.println(list2);

        list1.add(list2);
        System.out.println(list2);
        System.out.println(list1);

        if(list1.get(0) == list1.get(1)) {
            System.out.println("Lists at position 0 and 1 are the same");
        }

    }
}

这不是你在代码注释中写的"猫被两只狗代替",而是在最后,即在最后一条语句之后,list1包含两个列表,每个列表都包含一个"狗"。

当然,这是因为当您第二次将list2添加到list1时,实际上并不是添加新的列表,而是添加相同的列表。您可能认为,通过清除list2,然后再次添加它,可以添加一个新的列表,其中包含一个新项目"dog",但实际上您所做的是修改相同的对象并添加相同的引用。记住,list2list1是参考!

您需要做的是创建一个新的ArrayList对象,例如:

1
2
3
ArrayList<String> list3 = new ArrayList<String>();
list3.add("Dog");
list1.add(list3);

而不是清除list2并重新添加。

同时检查以下物品:

  • 为什么你不能在Java中有一个"列表<列表>字符串>"?

  • 使用Java中的列表列表工作

  • 什么是类、引用和对象?