仅将 ArrayList 作为值而不是引用传递

Posted

技术标签:

【中文标题】仅将 ArrayList 作为值而不是引用传递【英文标题】:Passing ArrayList as value only and not reference 【发布时间】:2013-03-24 14:31:37 【问题描述】:

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

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

【问题讨论】:

您可以通过Collections#unmodifiable(yourList) 发送一份不可修改的列表副本。 您还可以在修改它的方法中创建ArrayList 的新副本。虽然它不会影响第一个 ArrayList,但您在其中更改的任何对象仍将被更改... 您只修改列表吗?或者还有什么在列表里面? 有谁知道 System.arraycopy 是否只会复制引用或克隆数组中的对象?我找了源头,因为它是一个原生方法而结束了.. 【参考方案1】:

在现有答案的行中,但使用 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());

【讨论】:

【参考方案2】:

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

我会这样做:

void foo(final ArrayList list) 

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


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

【讨论】:

就可以了。我最初尝试将内部列表设置为等于参数,但这不起作用。这是迄今为止最简单的解决方案。 确实,需要等待一段时间才能接受答案。 当你有对象列表时它不起作用!通过更改对象,因为它们不是最终的,列表也发生了变化。【参考方案3】:

我不知道为什么,即使在new ArrayList&lt;MyObj&gt;(old) 之后,该对象仍在不应该更改的地方更改引用。所以我不得不实例化里面的对象的一个​​新副本。

我创建了一个复制构造函数,就像 ArrayList 上的那个一样

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

如果 Avi 的回答对你来说还不够,只是希望能帮助别人,比如我的代码太乱,甚至无法理解 =P

【讨论】:

【参考方案4】:

在你的方法中试试这个:

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
    

【讨论】:

更好的是new ArrayList&lt;Integer&gt;(list)【参考方案5】:

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

ArrayList copy = new ArrayList(original);

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

【讨论】:

您将如何做到修改副本成员不会修改原始列表?【参考方案6】:

克隆它。

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

在cmets中添加建议,也可以使用

ArrayList copy = new ArrayList(original);

还有

ArrayList copy = new ArrayList();
copy.addAll(original);

【讨论】:

恕我直言,这似乎太过分了,new ArrayList(list) 有什么问题? 我不知道new ArrayList(list)的存在。对不起。 @SriHarshaChilakapati 不要因为学习新东西而感到抱歉【参考方案7】:

您可以通过Collections#unmodifiableList(yourList) 发送一份不可修改的列表副本。顺便说一句,您的List&lt;Whatever&gt; 是从Java always pass by value 开始按值传递的,请注意,在foo(List&lt;Whatever&gt; 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...
    

【讨论】:

【参考方案8】:

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

【讨论】:

恕我直言,这似乎太过分了,new ArrayList(list) 有什么问题? 恕我直言 =“在我看来”

以上是关于仅将 ArrayList 作为值而不是引用传递的主要内容,如果未能解决你的问题,请参考以下文章

如果 Swift 通过值而不是引用传递,为啥我可以通过将 UIView 传递给函数来在 Swift 中操作 UIView 的属性? [复制]

java中参数传递--值传递,引用传递

Python 2.7 函数是不是记住值而不是引用?关闭怪异

按值而不是按引用复制对象

如何按值而不是按引用复制对象[重复]

c#基于值而不是引用调度扩展方法