我如何克隆一个数组列表,也克隆其项目在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中的对象不一样。
当前回答
一些其他用于将ArrayList复制为深度复制的替代方法
Alernative 1 -使用外部包common -lang3,方法SerializationUtils.clone():
SerializationUtils.clone()
假设我们有一个类dog,其中类的字段是可变的,并且至少有一个字段是String类型和mutable类型的对象——而不是基本数据类型(否则浅拷贝就足够了)。
浅拷贝的例子:
List<Dog> dogs = getDogs(); // We assume it returns a list of Dogs
List<Dog> clonedDogs = new ArrayList<>(dogs);
现在回到狗的深度复制。
Dog类只有可变字段。
狗类:
public class Dog implements Serializable {
private String name;
private int age;
public Dog() {
// Class with only mutable fields!
this.name = "NO_NAME";
this.age = -1;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
注意,类Dog实现了Serializable!这使得可以使用方法“SerializationUtils.clone(dog)”
阅读main方法中的注释以理解结果。这表明我们已经成功地对ArrayList()进行了深度复制。看到 在“SerializationUtils.clone(dog)”下面:
public static void main(String[] args) {
Dog dog1 = new Dog();
dog1.setName("Buddy");
dog1.setAge(1);
Dog dog2 = new Dog();
dog2.setName("Milo");
dog2.setAge(2);
List<Dog> dogs = new ArrayList<>(Arrays.asList(dog1,dog2));
// Output: 'List dogs: [Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]'
System.out.println("List dogs: " + dogs);
// Let's clone and make a deep copy of the dogs' ArrayList with external package commons-lang3:
List<Dog> clonedDogs = dogs.stream().map(dog -> SerializationUtils.clone(dog)).collect(Collectors.toList());
// Output: 'Now list dogs are deep copied into list clonedDogs.'
System.out.println("Now list dogs are deep copied into list clonedDogs.");
// A change on dog1 or dog2 can not impact a deep copy.
// Let's make a change on dog1 and dog2, and test this
// statement.
dog1.setName("Bella");
dog1.setAge(3);
dog2.setName("Molly");
dog2.setAge(4);
// The change is made on list dogs!
// Output: 'List dogs after change: [Dog{name='Bella', age=3}, Dog{name='Molly', age=4}]'
System.out.println("List dogs after change: " + dogs);
// There is no impact on list clonedDogs's inner objects after the deep copy.
// The deep copy of list clonedDogs was successful!
// If clonedDogs would be a shallow copy we would see the change on the field
// "private String name", the change made in list dogs, when setting the names
// Bella and Molly.
// Output clonedDogs:
// 'After change in list dogs, no impact/change in list clonedDogs:\n'
// '[Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]\n'
System.out.println("After change in list dogs, no impact/change in list clonedDogs: \n" + clonedDogs);
}
输出:
List dogs: [Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]
Now list dogs are deep copied into list clonedDogs.
List dogs after change: [Dog{name='Bella', age=3}, Dog{name='Molly', age=4}]
After change in list dogs, no impact/change in list clonedDogs:
[Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]
备注: 因为改变列表狗后对列表克隆狗没有影响/改变, 那么ArrayList的深度复制成功!
Alernative 2 -不使用外部包:
Dog类中引入了一个新方法“clone()”,与替代方案1相比,“implements Serializable”被删除了。
clone()
狗类:
public class Dog {
private String name;
private int age;
public Dog() {
// Class with only mutable fields!
this.name = "NO_NAME";
this.age = -1;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
/**
* Returns a deep copy of the Dog
* @return new instance of {@link Dog}
*/
public Dog clone() {
Dog newDog = new Dog();
newDog.setName(this.name);
newDog.setAge(this.age);
return newDog;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
阅读下面主要方法中的评论以理解结果。这表明我们已经成功地对ArrayList()进行了深度复制。看到 下面是上下文中的“clone()”方法:
public static void main(String[] args) {
Dog dog1 = new Dog();
dog1.setName("Buddy");
dog1.setAge(1);
Dog dog2 = new Dog();
dog2.setName("Milo");
dog2.setAge(2);
List<Dog> dogs = new ArrayList<>(Arrays.asList(dog1,dog2));
// Output: 'List dogs: [Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]'
System.out.println("List dogs: " + dogs);
// Let's clone and make a deep copy of the dogs' ArrayList:
List<Dog> clonedDogs = dogs.stream().map(dog -> dog.clone()).collect(Collectors.toList());
// Output: 'Now list dogs are deep copied into list clonedDogs.'
System.out.println("Now list dogs are deep copied into list clonedDogs.");
// A change on dog1 or dog2 can not impact a deep copy.
// Let's make a change on dog1 and dog2, and test this
// statement.
dog1.setName("Bella");
dog1.setAge(3);
dog2.setName("Molly");
dog2.setAge(4);
// The change is made on list dogs!
// Output: 'List dogs after change: [Dog{name='Bella', age=3}, Dog{name='Molly', age=4}]'
System.out.println("List dogs after change: " + dogs);
// There is no impact on list clonedDogs's inner objects after the deep copy.
// The deep copy of list clonedDogs was successful!
// If clonedDogs would be a shallow copy we would see the change on the field
// "private String name", the change made in list dogs, when setting the names
// Bella and Molly.
// Output clonedDogs:
// 'After change in list dogs, no impact/change in list clonedDogs:\n'
// '[Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]\n'
System.out.println("After change in list dogs, no impact/change in list clonedDogs: \n" + clonedDogs);
}
输出:
List dogs: [Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]
Now list dogs are deep copied into list clonedDogs.
List dogs after change: [Dog{name='Bella', age=3}, Dog{name='Molly', age=4}]
After change in list dogs, no impact/change in list clonedDogs:
[Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]
备注: 因为改变列表狗后对列表克隆狗没有影响/改变, 那么ArrayList的深度复制成功!
注一: 方案1比方案2慢得多, 但更容易维护,因为您不需要 更新任何方法,如clone()。
注2:对于替代方案1,以下maven依赖项用于方法“SerializationUtils.clone()””:
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
更多common-lang3版本请访问:
https://mvnrepository.com/artifact/org.apache.commons/commons-lang3
其他回答
一些其他用于将ArrayList复制为深度复制的替代方法
Alernative 1 -使用外部包common -lang3,方法SerializationUtils.clone():
SerializationUtils.clone()
假设我们有一个类dog,其中类的字段是可变的,并且至少有一个字段是String类型和mutable类型的对象——而不是基本数据类型(否则浅拷贝就足够了)。
浅拷贝的例子:
List<Dog> dogs = getDogs(); // We assume it returns a list of Dogs
List<Dog> clonedDogs = new ArrayList<>(dogs);
现在回到狗的深度复制。
Dog类只有可变字段。
狗类:
public class Dog implements Serializable {
private String name;
private int age;
public Dog() {
// Class with only mutable fields!
this.name = "NO_NAME";
this.age = -1;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
注意,类Dog实现了Serializable!这使得可以使用方法“SerializationUtils.clone(dog)”
阅读main方法中的注释以理解结果。这表明我们已经成功地对ArrayList()进行了深度复制。看到 在“SerializationUtils.clone(dog)”下面:
public static void main(String[] args) {
Dog dog1 = new Dog();
dog1.setName("Buddy");
dog1.setAge(1);
Dog dog2 = new Dog();
dog2.setName("Milo");
dog2.setAge(2);
List<Dog> dogs = new ArrayList<>(Arrays.asList(dog1,dog2));
// Output: 'List dogs: [Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]'
System.out.println("List dogs: " + dogs);
// Let's clone and make a deep copy of the dogs' ArrayList with external package commons-lang3:
List<Dog> clonedDogs = dogs.stream().map(dog -> SerializationUtils.clone(dog)).collect(Collectors.toList());
// Output: 'Now list dogs are deep copied into list clonedDogs.'
System.out.println("Now list dogs are deep copied into list clonedDogs.");
// A change on dog1 or dog2 can not impact a deep copy.
// Let's make a change on dog1 and dog2, and test this
// statement.
dog1.setName("Bella");
dog1.setAge(3);
dog2.setName("Molly");
dog2.setAge(4);
// The change is made on list dogs!
// Output: 'List dogs after change: [Dog{name='Bella', age=3}, Dog{name='Molly', age=4}]'
System.out.println("List dogs after change: " + dogs);
// There is no impact on list clonedDogs's inner objects after the deep copy.
// The deep copy of list clonedDogs was successful!
// If clonedDogs would be a shallow copy we would see the change on the field
// "private String name", the change made in list dogs, when setting the names
// Bella and Molly.
// Output clonedDogs:
// 'After change in list dogs, no impact/change in list clonedDogs:\n'
// '[Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]\n'
System.out.println("After change in list dogs, no impact/change in list clonedDogs: \n" + clonedDogs);
}
输出:
List dogs: [Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]
Now list dogs are deep copied into list clonedDogs.
List dogs after change: [Dog{name='Bella', age=3}, Dog{name='Molly', age=4}]
After change in list dogs, no impact/change in list clonedDogs:
[Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]
备注: 因为改变列表狗后对列表克隆狗没有影响/改变, 那么ArrayList的深度复制成功!
Alernative 2 -不使用外部包:
Dog类中引入了一个新方法“clone()”,与替代方案1相比,“implements Serializable”被删除了。
clone()
狗类:
public class Dog {
private String name;
private int age;
public Dog() {
// Class with only mutable fields!
this.name = "NO_NAME";
this.age = -1;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
/**
* Returns a deep copy of the Dog
* @return new instance of {@link Dog}
*/
public Dog clone() {
Dog newDog = new Dog();
newDog.setName(this.name);
newDog.setAge(this.age);
return newDog;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
阅读下面主要方法中的评论以理解结果。这表明我们已经成功地对ArrayList()进行了深度复制。看到 下面是上下文中的“clone()”方法:
public static void main(String[] args) {
Dog dog1 = new Dog();
dog1.setName("Buddy");
dog1.setAge(1);
Dog dog2 = new Dog();
dog2.setName("Milo");
dog2.setAge(2);
List<Dog> dogs = new ArrayList<>(Arrays.asList(dog1,dog2));
// Output: 'List dogs: [Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]'
System.out.println("List dogs: " + dogs);
// Let's clone and make a deep copy of the dogs' ArrayList:
List<Dog> clonedDogs = dogs.stream().map(dog -> dog.clone()).collect(Collectors.toList());
// Output: 'Now list dogs are deep copied into list clonedDogs.'
System.out.println("Now list dogs are deep copied into list clonedDogs.");
// A change on dog1 or dog2 can not impact a deep copy.
// Let's make a change on dog1 and dog2, and test this
// statement.
dog1.setName("Bella");
dog1.setAge(3);
dog2.setName("Molly");
dog2.setAge(4);
// The change is made on list dogs!
// Output: 'List dogs after change: [Dog{name='Bella', age=3}, Dog{name='Molly', age=4}]'
System.out.println("List dogs after change: " + dogs);
// There is no impact on list clonedDogs's inner objects after the deep copy.
// The deep copy of list clonedDogs was successful!
// If clonedDogs would be a shallow copy we would see the change on the field
// "private String name", the change made in list dogs, when setting the names
// Bella and Molly.
// Output clonedDogs:
// 'After change in list dogs, no impact/change in list clonedDogs:\n'
// '[Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]\n'
System.out.println("After change in list dogs, no impact/change in list clonedDogs: \n" + clonedDogs);
}
输出:
List dogs: [Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]
Now list dogs are deep copied into list clonedDogs.
List dogs after change: [Dog{name='Bella', age=3}, Dog{name='Molly', age=4}]
After change in list dogs, no impact/change in list clonedDogs:
[Dog{name='Buddy', age=1}, Dog{name='Milo', age=2}]
备注: 因为改变列表狗后对列表克隆狗没有影响/改变, 那么ArrayList的深度复制成功!
注一: 方案1比方案2慢得多, 但更容易维护,因为您不需要 更新任何方法,如clone()。
注2:对于替代方案1,以下maven依赖项用于方法“SerializationUtils.clone()””:
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
更多common-lang3版本请访问:
https://mvnrepository.com/artifact/org.apache.commons/commons-lang3
我一直使用这个选项:
ArrayList<Dog> clonedList = new ArrayList<Dog>(name_of_arraylist_that_you_need_to_Clone);
对于你的对象重写clone()方法
class You_class {
int a;
@Override
public You_class clone() {
You_class you_class = new You_class();
you_class.a = this.a;
return you_class;
}
}
调用.clone() for Vector obj或ArraiList obj....
您可以使用JSON(带有JSON库)来序列化和反序列化列表。序列化后的列表在未序列化时不包含对原始对象的引用。
使用谷歌GSON:
List<CategoryModel> originalList = new ArrayList<>(); // add some items later
String listAsJson = gson.toJson(originalList);
List<CategoryModel> newList = new Gson().fromJson(listAsJson, new TypeToken<List<CategoryModel>>() {}.getType());
你也可以使用其他JSON库,比如Jackson。
使用这种方法的优点是可以解决问题,而不必创建类、接口和克隆逻辑(如果对象内部有其他对象列表,克隆逻辑可能会很长)
我刚刚开发了一个库,能够克隆一个实体对象和java.util.List对象。只需从https://drive.google.com/open?id=0B69Sui5ah93EUTloSktFUkctN0U下载jar,并使用静态方法cloneListObject(List List)。该方法不仅克隆List,而且克隆所有实体元素。