40

简单地说,我有一个带有 ArrayList 参数的方法。在该方法中,我修改 ArrayList 的内容仅与该方法返回的内容相关。因此,我不希望作为参数传递的 ArrayList 受到影响(即不作为参考传递)。

我所尝试的一切都未能达到预期的效果。我需要做什么才能仅在方法中使用 ArrayList 的副本,而不是让它更改实际变量?

4

8 回答 8

51

即使您有办法将数组列表作为副本而不是通过引用传递,它也只是一个浅拷贝。

我会做类似的事情:

void foo(final ArrayList list) {

    ArrayList listCopy = new ArrayList(list);
    // Rest of the code

}

只需在复制的列表上工作。

于 2013-04-03T04:07:00.150 回答
21

您可以使用 ArrayList 的复制构造函数创建 ArrayList 的副本:

ArrayList copy = new ArrayList(original);

但是如果列表的元素也是对象,那么您必须知道修改副本的成员也会修改原始成员中的那个成员。

于 2013-04-03T04:09:50.440 回答
5

您可以通过Collections#unmodifiableList(yourList)以发送列表的不可修改副本。顺便说一句,你List<Whatever>是按值传递的,因为Java 总是按值传递,注意在foo(List<Whatever> list)方法中你不能修改list值,但你可以修改它的内容

public class MyClass {

    List<Whatever> list = new ArrayList<Whatever>();

    public void bar() {
        //filling list...
        foo(Collections.unmodifiableList(list));
    }

    public void foo(List<Whatever> list) {
        //do what you want with list except modifying it...
    }
}
于 2013-04-03T04:07:10.193 回答
3

您可以使用该.clone方法或 aCopyOnWriteArrayList进行复制,从而不会影响原件。

于 2013-04-03T04:06:30.877 回答
3

在你的方法中试试这个:

void method(List<Integer> list) {
        List copyList =  new ArrayList<Integer>();
        copyList.addAll(list); // This will create a copy of all the emlements of your original list
    }
于 2013-04-03T04:11:53.470 回答
3

我不确定为什么,即使new ArrayList<MyObj>(old)对象仍在不应该更改的地方更改引用。所以我不得不在里面实例化一个新的对象副本。

我制作了一个复制构造函数,就像 ArrayList 上的一样,并且确实喜欢

 newArray = new ArrayList<MyObj>();
        for (int i = 0; i < oldArray.size(); i++) {
            newArray.add(new MyObj(ondArray.get(i)));
        }

如果 Avi 的答案在您的情况下还不够,只是希望能帮助其他人,就像我的代码太乱,甚至无法理解 =P

于 2015-01-21T12:34:41.143 回答
1

只需克隆它。

public ArrayList cloneArrayList(ArrayList lst){
    ArrayList list = new ArrayList();
    for (int i=0; i<lst.size(); i++){
        list.add(lst.get(i));
    }
    return list;
}

在评论中添加建议,您也可以使用

ArrayList copy = new ArrayList(original);

并且

ArrayList copy = new ArrayList();
copy.addAll(original);
于 2013-04-03T04:07:11.613 回答
0

根据现有答案,但使用 ArrayList API。你可以使用subList(fromIndex, toIndex)方法。它显式地创建仅包含所需元素的列表视图(当然,按顺序)。在这里,即使你用添加/删除等操作修改了视图,它也不会改变原来的列表。它使您免于显式创建副本。

像这样的东西:

public void recursiveMethod(List<Integer> list) {
    if(base)
         return;
    recursiveCall(list);

    // following will just create a tail list but will not actually modify the list
    recursiveCall(list.subList(1, list.size());
}
于 2016-09-07T04:36:56.863 回答