如何在构造函数中正确克隆列表?

How to clone the List correctly in the constructor?

构造函数以一个List为参数,这个List需要填充相同的元素,比如"1",克隆7次,将结果分配给不同的集合,这样7个方法分别处理他们的名单。

构造函数调用:

public Class1 {
    public Class2 arrayList = new Class2(new ArrayList<>(10000))
    public Class2 linkedList = new Class2(new LinkedList<>())
    public Class2 cowList = new Class2(new CopyOnWriteArrayList<>())
}

public Class2 {

    private List<Integer> list;
    private List<Integer> list2;
    private List<Integer> list3;
    private List<Integer> list4;
    private List<Integer> list5;
    private List<Integer> list6;
    private List<Integer> list7;

    public Class2(List<Integer> list) {

        for (int i = 0; i < list.size(); i++) {
            list.add(1);
        }

        this.list = list;
        this.list2 = list;
        this.list3 = list;
        this.list4 = list;
        this.list5 = list;
        this.list6 = list;
        this.list7 = list;
    }

    method1(){
        // list - doSomething...;
    }

    method2(){
        // list1 - doSomething...;
    }

    method3(){
        // list2 - doSomething...;
    }    

    method4(){
        // list3 - doSomething...;
    }

    ...

}

每个方法对其列表执行特定操作。根据调用的构造函数,列表为 - ArrayListLinkedListCopyOnWriteArrayList

我的代码不起作用。我做错了什么?

使用下面的语句,您的所有列表都指向相同的内存位置,因此列表上的任何操作对所有 list1 到 list7 都是可见的。

this.list = list; this.list2 = list; this.list3 = list;

相反,您需要使用适当的列表构造函数生成一个包含输入列表元素的新数组列表,该列表构造函数接受 Collection 作为参数。

由于输入可以是任何 List 类型,您可以使用 instanceof 检查输入类型并调用适当的构造函数。

注意:您只是在创建一个新列表。因此,对原始列表的更改不会反映在这七个列表中。但是列表中包含的对象仍然在新列表中引用,因为我们没有克隆对象。我们只是创建一个包含相同对象的新列表。因此,如果您使用 List<SomeObject> 而不是 List<Integer>,如果 SomeObject 是可变的,那么对对象的任何操作都会反映在每个列表中。这不适用于此特定问题,因为它使用不可变的 Integer 对象。

private static List<Integer> copy(List<Integer> input) {
    if(input instanceof ArrayList) {
        return new ArrayList<>(input);
    } else if (input instanceof LinkedList) {
        return new LinkedList<>(input);
    }
    // others
    ...............
    ...............

}

现在在您的 class' 构造函数中调用此方法。

this.list = copy(list);
this.list2 = copy(list);
this.list3 = copy(list);

您也可以将开头的 for 循环替换为以下内容:

Collections.fill(list, 1);

但是使用当前代码,所有输入都是空的,因此您传递的每个列表的 size 将是 0。因此不会发生元素填充(使用 for 循环或 Collections.fill

new ArrayList<>(10000) 不更新 arraylist 的大小。它只初始化支持数组。

也读