java中List的浅拷贝与深拷贝
阅读原文时间:2023年07月08日阅读:4

众所周知,list本质上是数组,而数组的是以地址的形式进行存储。

如上图将list A浅拷贝给list B,由于进行的是浅拷贝,所以直接将A的内容复制给了B,java中相同内容的数组指向同一地址,即进行浅拷贝后A与B指向同一地址。

造成的后果就是,改变B的同时也会改变A,因为改变B就是改变B所指向地址的内容,由于A也指向同一地址,所以A与B一起改变。

几种浅拷贝

1、遍历循环复制

List destList=new ArrayList(srcList.size());
for(Person p : srcList){
destList.add(p);
}

2、使用List实现类的构造方法

List destList=new ArrayList(srcList);

3、使用list.addAll()方法

List destList=new ArrayList();
destList.addAll(srcList);

4、使用System.arraycopy()方法

Person[] srcPersons=srcList.toArray(new Person[0]);
Person[] destPersons=new Person[srcPersons.length];
System.arraycopy(srcPersons, 0, destPersons, 0, srcPersons.length);

测试及结果

printList(destList); //打印未改变B之前的A
srcList.get(0).setAge(100);//改变B
printList(destList); //打印改变B后的A

//打印结果
123-->20
ABC-->21
abc-->22
123-->100
ABC-->21
abc-->22

如图,深拷贝就是将A复制给B的同时,给B创建新的地址,再将地址A的内容传递到地址B。ListA与ListB内容一致,但是由于所指向的地址不同,所以改变相互不受影响。

深拷贝的方法

1.利用CollectionUtils的mergeArrayIntoCollection和Collections.copy结合实现深拷贝

public class TechSysVo {

@Getter  
@Setter  
private Long id;

@Getter  
@Setter  
private String name;

public TechSysVo() {  
}  

}

import com.wsh.clone.arraylist.TechSysVo;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class App {

public static void main(String\[\] args) {  
    TechSysVo techSysVo = new TechSysVo();  
    TechSysVo techSysVo1 = new TechSysVo();  
    List<TechSysVo> list = new ArrayList<>();  
    list.add(techSysVo);  
    list.add(techSysVo1);  
    //list深度拷贝  
    List<TechSysVo> newList = new ArrayList<>();  
    CollectionUtils.mergeArrayIntoCollection(new Object\[list.size()\],newList);  
    Collections.copy(newList, list);  
    //拷贝完清空result  
    list.clear();  
    System.out.println(list.toString());  
    System.out.println(newList.toString());

}

}

2.使用序列化方法

public class TechSysVo implements Serializable {

@Getter  
@Setter  
private Long id;

@Getter  
@Setter  
private String name;

public TechSysVo() {  
}  

}

public static List deepCopy(List src) {
try {
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(byteOut);
out.writeObject(src);

        ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());  
        ObjectInputStream in = new ObjectInputStream(byteIn);  
        @SuppressWarnings("unchecked")  
        List<T> dest = (List<T>) in.readObject();  
        return dest;  
    }catch (Exception e){  
        e.printStackTrace();  
    }  
    return null;  

}

public static void main(String[] args) {
TechSysVo techSysVo = new TechSysVo();
TechSysVo techSysVo1 = new TechSysVo();
List list = new ArrayList<>();
list.add(techSysVo);
list.add(techSysVo1);
//list深度拷贝
List newList = new ArrayList<>();
newList = deepCopy(list);
//拷贝完清空result
list.clear();
System.out.println(list.toString());
System.out.println(newList.toString());

}

3.使用Java8的新特性的Stream实现深拷贝

public static void main(String[] args) {
TechSysVo techSysVo = new TechSysVo();
TechSysVo techSysVo1 = new TechSysVo();
List list = new ArrayList<>();
list.add(techSysVo);
list.add(techSysVo1);
//list深度拷贝
List newList = list.stream().collect(Collectors.toList());
//拷贝完清空result
list.clear();
System.out.println(list.toString());
System.out.println(newList.toString());
}

在浅复制的情况下,源数据被修改破坏之后,使用相同引用指向该数据的目标集合中的对应元素也就发生了相同的变化。

因此,在需求要求必须深复制的情况下,要是使用上面提到的方法,请确保List中的T类对象是不易被外部修改和破坏的。

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章