仅将 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<MyObj>(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<Integer>(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<Whatever>
是从Java always pass by value 开始按值传递的,请注意,在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...
【讨论】:
【参考方案8】:您可以使用.clone
方法或CopyOnWriteArrayList
进行复制,从而不会影响原件。
【讨论】:
恕我直言,这似乎太过分了,new ArrayList(list)
有什么问题?
恕我直言 =“在我看来”以上是关于仅将 ArrayList 作为值而不是引用传递的主要内容,如果未能解决你的问题,请参考以下文章
如果 Swift 通过值而不是引用传递,为啥我可以通过将 UIView 传递给函数来在 Swift 中操作 UIView 的属性? [复制]