浅谈Java语言中List集合复制(浅克隆与深度克隆)
程序员文章站
2022-09-26 22:54:16
List常见的复制方式:首先准备一个实体类:public class User { private String userName; private Integer age; public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName;...
List常见的复制方式:
首先准备一个实体类:
public class User {
private String userName;
private Integer age;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public User(String userName, Integer age) {
this.userName = userName;
this.age = age;
}
public User() {
}
@Override public String toString() {
return "User{" + "userName='" + userName + '\'' + ", age=" + age + '}';
}
}
其次构造原始List集合
private List<User> sourceList = new ArrayList<>();
@Before public void setUp() throws Exception {
sourceList.add(new User("Tom",21));
sourceList.add(new User("Lucy",22));
sourceList.add(new User("Jack",23));
}
方式一:
@Test
public void shallowCopyAddAll() {
System.out.println("Copy before -> sourceList-> "+ sourceList);
System.out.println("**********************************************");
List<User> targetList = new ArrayList<>();
targetList.addAll(sourceList);
targetList.get(0).setAge(30);
System.out.println("After the copy -> sourceList-> "+sourceList);
System.out.println("After the copy -> targetList-> "+targetList);
}
结果:
Copy before -> sourceList-> [User{userName='Tom', age=21}, User{userName='Lucy', age=22}, User{userName='Jack', age=23}]
**********************************************
After the copy -> sourceList-> [User{userName='Tom', age=30}, User{userName='Lucy', age=22}, User{userName='Jack', age=23}]
After the copy -> targetList-> [User{userName='Tom', age=30}, User{userName='Lucy', age=22}, User{userName='Jack', age=23}]
修改克隆集合中的值,源集合也随之发生了变化。
方式二:
@Test
public void shallowCopy() {
System.out.println("Copy before -> sourceList-> "+ sourceList);
System.out.println("**********************************************");
List<User> targetList = new ArrayList<>(sourceList);
targetList.get(0).setAge(40);
System.out.println("After the copy -> sourceList-> "+sourceList);
System.out.println("After the copy -> targetList-> "+targetList);
}
结果:
Copy before -> sourceList-> [User{userName='Tom', age=21}, User{userName='Lucy', age=22}, User{userName='Jack', age=23}]
**********************************************
After the copy -> sourceList-> [User{userName='Tom', age=40}, User{userName='Lucy', age=22}, User{userName='Jack', age=23}]
After the copy -> targetList-> [User{userName='Tom', age=40}, User{userName='Lucy', age=22}, User{userName='Jack', age=23}]
修改克隆集合中的值,源集合也随之发生了变化。
方式三:
@Test
public void shallowCopySysCopy() {
System.out.println("Copy before -> sourceList-> "+ sourceList);
System.out.println("**********************************************");
User[] targets = new User[sourceList.size()];
Object[] sources = sourceList.toArray();
System.arraycopy(sources,0,targets,0,sourceList.size());
targets[0].setAge(50);
System.out.println("After the copy -> sourceList-> "+ Arrays.asList(sources));
System.out.println("After the copy -> targetList-> "+Arrays.asList(targets));
}
结果:
Copy before -> sourceList-> [User{userName='Tom', age=21}, User{userName='Lucy', age=22}, User{userName='Jack', age=23}]
**********************************************
After the copy -> sourceList-> [User{userName='Tom', age=50}, User{userName='Lucy', age=22}, User{userName='Jack', age=23}]
After the copy -> targetList-> [User{userName='Tom', age=50}, User{userName='Lucy', age=22}, User{userName='Jack', age=23}]
修改克隆集合中的值,源集合也随之发生了变化。
方式四:
@Test
public void shallowCopyCollectionsCopy() {
System.out.println("Copy before -> sourceList-> "+ sourceList);
System.out.println("**********************************************");
List<User> targetList = new ArrayList<>();
Collections.addAll(targetList,new User[sourceList.size()]);
Collections.copy(targetList,sourceList);
targetList.get(0).setAge(51);
System.out.println("After the copy -> sourceList-> "+ sourceList);
System.out.println("After the copy -> targetList-> "+targetList);
}
结果:
Copy before -> sourceList-> [User{userName='Tom', age=21}, User{userName='Lucy', age=22}, User{userName='Jack', age=23}]
**********************************************
After the copy -> sourceList-> [User{userName='Tom', age=51}, User{userName='Lucy', age=22}, User{userName='Jack', age=23}]
After the copy -> targetList-> [User{userName='Tom', age=51}, User{userName='Lucy', age=22}, User{userName='Jack', age=23}]
修改克隆集合中的值,源集合也随之发生了变化。
方式五:
@Test
public void shallowCopyCollectionsAddAll() {
System.out.println("Copy before -> sourceList-> "+ sourceList);
System.out.println("**********************************************");
List<User> targetList = new ArrayList<>();
User[] sources = new User[sourceList.size()];
for (int i = 0; i < sourceList.size(); i++) {
sources[i] = sourceList.get(i);
}
Collections.addAll(targetList,sources);
targetList.get(0).setAge(52);
System.out.println("After the copy -> sourceList-> "+ sourceList);
System.out.println("After the copy -> targetList-> "+targetList);
}
结果:
Copy before -> sourceList-> [User{userName='Tom', age=21}, User{userName='Lucy', age=22}, User{userName='Jack', age=23}]
**********************************************
After the copy -> sourceList-> [User{userName='Tom', age=52}, User{userName='Lucy', age=22}, User{userName='Jack', age=23}]
After the copy -> targetList-> [User{userName='Tom', age=52}, User{userName='Lucy', age=22}, User{userName='Jack', age=23}]
修改克隆集合中的值,源集合也随之发生了变化。
方式六:
@Test
public void shallowCopyCycle() {
System.out.println("Copy before -> sourceList-> "+ sourceList);
System.out.println("**********************************************");
List<User> targetList = new ArrayList<>();
for (int i = 0; i < sourceList.size(); i++) {
targetList.add(sourceList.get(i));
}
targetList.get(0).setAge(60);
System.out.println("After the copy -> sourceList-> "+sourceList);
System.out.println("After the copy -> targetList-> "+targetList);
}
结果:
Copy before -> sourceList-> [User{userName='Tom', age=21}, User{userName='Lucy', age=22}, User{userName='Jack', age=23}]
**********************************************
After the copy -> sourceList-> [User{userName='Tom', age=60}, User{userName='Lucy', age=22}, User{userName='Jack', age=23}]
After the copy -> targetList-> [User{userName='Tom', age=60}, User{userName='Lucy', age=22}, User{userName='Jack', age=23}]
修改克隆集合中的值,源集合也随之发生了变化。
方式七:
@Test
public void shallowCopyForEach() {
System.out.println("Copy before -> sourceList-> "+ sourceList);
System.out.println("**********************************************");
List<User> targetList = new ArrayList<>();
sourceList.forEach(user -> {
targetList.add(user);
});
targetList.get(0).setAge(70);
System.out.println("After the copy -> sourceList-> "+sourceList);
System.out.println("After the copy -> After the copy -> targetList-> "+targetList);
}
结果:
Copy before -> sourceList-> [User{userName='Tom', age=21}, User{userName='Lucy', age=22}, User{userName='Jack', age=23}]
**********************************************
After the copy -> sourceList-> [User{userName='Tom', age=70}, User{userName='Lucy', age=22}, User{userName='Jack', age=23}]
After the copy -> After the copy -> targetList-> [User{userName='Tom', age=70}, User{userName='Lucy', age=22}, User{userName='Jack', age=23}]
修改克隆集合中的值,源集合也随之发生了变化。
场景: 如果只是单纯的复制集合,以上几种方法都适用。如果修改克隆的集合的值,而又不影响源集合中的值,以上方法就不适用了。因为以上方法克隆List集合时,只是改变了List集合中元素的引用,引用的地址却没有发生变化,导致在操作克隆集合的同时源集合的元素也会相应发生变化。
解决方案:(进行深层次的复制)
一: 的复制集合的同时创建新的对象(New ),再放入克隆的集合,这时改变克隆的集合,源集合对应的元素就不会发生变化。
二:使用IO流,把对象序列化到流中,当然这种方法肯定会要开辟新的堆内存。所以实体类必须要实现序列化接口
优化实体类:
public class User implements Serializable {
private String userName;
private Integer age;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public User(String userName, Integer age) {
this.userName = userName;
this.age = age;
}
public User() {
}
@Override public String toString() {
return "User{" + "userName='" + userName + '\'' + ", age=" + age + '}';
}
}
工具类:
public static<E> List<E> deepCopy(List<E> sourceList) throws IOException, ClassNotFoundException {
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(byteOut);
out.writeObject(sourceList);
ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
ObjectInputStream in = new ObjectInputStream(byteIn);
@SuppressWarnings("unchecked")
List<E> dest = (List<E>) in.readObject();
return dest;
}
使用方式:
@Test
public void shallowCopyDeepCopy() throws IOException, ClassNotFoundException {
System.out.println("Copy before -> sourceList-> "+ sourceList);
System.out.println("**********************************************");
List<User> targetList = ListUtils.deepCopy(sourceList);
targetList.get(0).setAge(80);
targetList.get(1).setAge(91);
System.out.println("After the copy -> sourceList-> "+sourceList);
System.out.println("After the copy -> After the copy -> targetList-> "+targetList);
}
结果:
Copy before -> sourceList-> [User{userName='Tom', age=21}, User{userName='Lucy', age=22}, User{userName='Jack', age=23}]
**********************************************
After the copy -> sourceList-> [User{userName='Tom', age=21}, User{userName='Lucy', age=22}, User{userName='Jack', age=23}]
After the copy -> After the copy -> targetList-> [User{userName='Tom', age=80}, User{userName='Lucy', age=91}, User{userName='Jack', age=23}]
修改克隆后集合的元素,源集合对应的元素没有发生任何变化,这就实现了深度克隆集合,不相互影响。
本文地址:https://blog.csdn.net/jinchunzhao123/article/details/108025823
上一篇: 芝士可以直接吃么?芝士还可以怎么吃?
下一篇: 武则天跟李世民为什么没有孩子?原因是什么