JAVA中带有克隆方法的迭代器VS ArrayList.addAll()
Posted
技术标签:
【中文标题】JAVA中带有克隆方法的迭代器VS ArrayList.addAll()【英文标题】:Iterators VS ArrayList.addAll() with clone method in JAVA 【发布时间】:2015-11-23 23:47:22 【问题描述】:我的问题是基于ArrayList.addAll()
方法不会生成新对象而是将相同的对象附加到 ArrayList 的假设。
因此,为了addAll
对象但也有新对象,则必须进行构造。
例如,假设 BooClass 类实现了具有深拷贝的Cloneable
接口,我们有:
ArrayList<BooClass> foo1 = new ArrayList<BooClass>();
for (int i = 0; i < 10; i++) foo1.add(new BooClass());
ArrayList<BooClass> foo2 = new ArrayList<BooClass>();
然后,如果有人想将foo1
的所有元素添加到foo2
作为new 对象,他应该这样做:
foo2.addAll(foo1.clone());
因为:
foo2.addAll(foo1);
将导致 (?) foo1
和 foo2
在其中具有相同的 BooClass
对象。
所以,如果以上是正确的,那么我的问题是两者哪个更快:
Iterator<BooClass> itBoo = foo1.iterator();
while(itBoo.hasNext()) foo2.add(itBoo.next().clone());
或:
foo2.addAll(foo1.clone());
?
【问题讨论】:
1.没关系。 2.如果真的很重要,你可以自己测试一下。 3. 除非您说的是数百万份/克隆,否则没关系。 那么,两者对于流程的复杂度“程度”是一样的吗? 是的,他们都是O(n)
。迭代器方法不太清楚。
实际上它们并不相同(嗯,在复杂性方面是的,但不是功能)。 ArrayList.clone();
不会产生深度克隆。所以相当于一个简单的addAll()
。
ArrayList.clone
返回浅拷贝。 foo2.addAll(foo1.clone())
与 foo2.addAll(foo1);
的结果相同
【参考方案1】:
两者不做同样的事情。
Iterator<BooClass> itBoo = foo1.iterator();
while(itBoo.hasNext()) foo2.add(itBoo.next().clone());
这会克隆foo1
中的每个BooClass
对象,并将克隆添加到foo2
。
而
foo2.addAll(foo1.clone());
克隆 列表 foo1
,生成一个新的 ArrayList,其中包含对 foo1 相同的 BooClass 对象的引用,并将所有这些 BooClass
对象添加到 foo2
。
顺便说一句,克隆操作完全没用,因为这与简单的操作具有相同的效果
foo2.addAll(foo1);
如果你想要一个深度克隆,最简单的方法是
List<BooClass> foo2 = new ArrayList<>(foo1.size());
for (BooClass boo : foo1)
foo2.add(boo.clone());
请注意,clone() 通常被认为是一个坏主意。您通常应该更喜欢复制构造函数:
List<BooClass> foo2 = new ArrayList<>(foo1.size());
for (BooClass boo : foo1)
foo2.add(new BooClass(boo));
【讨论】:
foo1
上的clone()
不会导致调用ArrayList
中的对象的clone()
?如果是这种情况,那么通过调用addAll()
,您只需将foo1
的same 对象添加到foo2
?
@Kostas 你明白了。 clone() 不是递归的。这是documented:返回此 ArrayList 实例的浅表副本。 (元素本身不会被复制。)
那么,在clone
方法中实际执行复制构造功能是否被认为是一种好习惯?
什么意思?您不能更改 ArrayList.clone() 的实现。因此,您必须明确创建列表中每个元素的克隆。最好的方法是避免使用损坏且设计不良的 clone() ,而是使用复制构造函数。
最好的做法是忘记 clone() 并提供一个复制构造函数:public BooClass(BooClass oldObject)
以上是关于JAVA中带有克隆方法的迭代器VS ArrayList.addAll()的主要内容,如果未能解决你的问题,请参考以下文章