我如何克隆一个数组列表,也克隆其项目在Java?
例如,我有:
ArrayList<Dog> dogs = getDogs();
ArrayList<Dog> clonedList = ....something to do with dogs....
我希望clonedList中的对象与dogs list中的对象不一样。
我如何克隆一个数组列表,也克隆其项目在Java?
例如,我有:
ArrayList<Dog> dogs = getDogs();
ArrayList<Dog> clonedList = ....something to do with dogs....
我希望clonedList中的对象与dogs list中的对象不一样。
当前回答
下面的方法对我有用。
在Dog.java
public Class Dog{
private String a,b;
public Dog(){} //no args constructor
public Dog(Dog d){ // copy constructor
this.a=d.a;
this.b=d.b;
}
}
-------------------------
private List<Dog> createCopy(List<Dog> dogs) {
List<Dog> newDogsList= new ArrayList<>();
if (CollectionUtils.isNotEmpty(dogs)) {
dogs.stream().forEach(dog-> newDogsList.add((Dog) SerializationUtils.clone(dog)));
}
return newDogsList;
}
在这里,由createCopy方法创建的新列表是通过SerializationUtils.clone()创建的。 因此,对新列表所做的任何更改都不会影响原始列表
其他回答
我认为目前的绿色答案很糟糕,为什么你会问?
它可能需要添加大量代码 它要求你列出所有要复制的列表并这样做
序列化的方式在我看来也是不好的,你可能不得不到处添加Serializable。
那么解决方案是什么呢?
Java深度克隆库 克隆库是一个小型的开源(apache许可)java库,它对对象进行深度克隆。对象不必实现克隆接口。实际上,这个库可以克隆任何java对象。它可以用在缓存实现中,如果你不想修改缓存对象,或者当你想创建对象的深度副本时。
Cloner cloner=new Cloner();
XX clone = cloner.deepClone(someObjectOfTypeXX);
请登录https://github.com/kostaskougios/cloning查看
基本上有三种不需要手动迭代的方法,
1使用构造函数
ArrayList<Dog> dogs = getDogs();
ArrayList<Dog> clonedList = new ArrayList<Dog>(dogs);
2使用addAll(Collection<?c)扩展;
ArrayList<Dog> dogs = getDogs();
ArrayList<Dog> clonedList = new ArrayList<Dog>();
clonedList.addAll(dogs);
3使用addAll(int index, Collection<?用int形参扩展E> c)方法
ArrayList<Dog> dogs = getDogs();
ArrayList<Dog> clonedList = new ArrayList<Dog>();
clonedList.addAll(0, dogs);
注意:如果指定的集合在操作进行时被修改,这些操作的行为将是未定义的。
简单的方法是
ArrayList<Dog> dogs = getDogs();
ArrayList<Dog> clonedList = new ArrayList<Dog>(dogs);
我一直使用这个选项:
ArrayList<Dog> clonedList = new ArrayList<Dog>(name_of_arraylist_that_you_need_to_Clone);
Java 8提供了一种优雅而简洁地调用元素狗的复制构造函数或克隆方法的新方法:流、lambdas和收集器。
拷贝构造函数:
List<Dog> clonedDogs = dogs.stream().map(Dog::new).collect(toList());
表达式Dog::new被称为方法引用。它创建了一个函数对象,调用Dog上的构造函数,该构造函数以另一个Dog作为参数。
克隆方法[1]:
List<Dog> clonedDogs = dogs.stream().map(Dog::clone).collect(toList());
得到一个数组列表作为结果
或者,如果你必须得到一个数组列表(以防你以后想修改它):
ArrayList<Dog> clonedDogs = dogs.stream().map(Dog::new).collect(toCollection(ArrayList::new));
及时更新列表
如果你不需要保留狗列表的原始内容,你可以使用replaceAll方法并在适当的地方更新列表:
dogs.replaceAll(Dog::new);
所有示例都假设导入静态java.util.stream.Collectors.*;
数组列表收集器
上一个例子中的收集器可以被做成一个util方法。因为这是一件很常见的事情,我个人喜欢它是短而漂亮的。是这样的:
ArrayList<Dog> clonedDogs = dogs.stream().map(d -> d.clone()).collect(toArrayList());
public static <T> Collector<T, ?, ArrayList<T>> toArrayList() {
return Collectors.toCollection(ArrayList::new);
}
[1] CloneNotSupportedException异常说明:
为了使这个解决方案工作,Dog的克隆方法不能声明它抛出CloneNotSupportedException。原因是map的参数不允许抛出任何受控异常。
是这样的:
// Note: Method is public and returns Dog, not Object
@Override
public Dog clone() /* Note: No throws clause here */ { ...
然而,这应该不是一个大问题,因为这是最佳实践。(例如,effective Java给出了这个建议。)
感谢Gustavo注意到这一点。