如何克隆ArrayList并克隆其内容?
我如何克隆一个ArrayList
并且在Java中克隆它的项目?
例如,我有:
ArrayList<Dog> dogs = getDogs();
ArrayList<Dog> clonedList = ....something to do with dogs....
我期望clonedList
中的对象与狗列表中的对象不同。
您需要对这些项目进行迭代,并逐个克隆它们,随时将克隆放入结果数组中。
public static List<Dog> cloneList(List<Dog> list) {
List<Dog> clone = new ArrayList<Dog>(list.size());
for (Dog item : list) clone.add(item.clone());
return clone;
}
为了达到这个目的,显然你必须让你的Dog对象实现Cloneable接口和clone()方法。
我个人会为Dog添加一个构造函数:
class Dog
{
public Dog()
{ ... } // Regular constructor
public Dog(Dog dog) {
// Copy all the fields of Dog.
}
}
然后迭代(如Varkhan的答案所示):
public static List<Dog> cloneList(List<Dog> dogList) {
List<Dog> clonedList = new ArrayList<Dog>(dogList.size());
for (Dog dog : dogList) {
clonedList.add(new Dog(dog));
}
return clonedList;
}
我发现这个优点是你不需要在Java中使用破解的Cloneable东西。 它也与您复制Java集合的方式相匹配。
另一种选择是编写自己的ICloneable接口并使用它。 这样你就可以编写一个通用的克隆方法。
所有标准集合都有复制构造函数。 使用它们。
List<Double> original = // some list
List<Double> copy = new ArrayList<Double>(original); //This does a shallow copy
clone()
被设计成有几个错误(见这个问题),所以最好避免它。
从Effective Java 2nd Edition开始,第11项:明智地重写克隆
鉴于所有与Cloneable相关的问题,可以肯定地说其他接口不应该扩展它,并且为继承设计的类(Item 17)不应该实现它。 由于它的许多缺点,一些专家程序员只是选择从不重写克隆方法,并且从不调用它,除非可能复制数组。 如果您为继承设计类,请注意,如果您选择不提供良好行为的受保护克隆方法,则子类无法实现Cloneable。
本书还介绍了拷贝构造函数对Cloneable / clone的许多优点。
考虑使用拷贝构造函数的另一个好处:假设你有一个HashSet s
,并且你想将它拷贝为TreeSet
。 克隆方法不能提供此功能,但使用转换构造函数很容易: new TreeSet(s)
。