深拷贝List<Object>

87 阅读2分钟

深拷贝的几种方式

先准备了一些测试类,Student,School类

package clonePackage.deepcopy;

import java.io.Serializable;

public class Student implements Serializable {
    private String id;
    private int age;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id='" + id + ''' +
                ", age=" + age +
                '}';
    }
}
package clonePackage.deepcopy;

import java.io.Serializable;
import java.util.List;

public class School implements Serializable {
    private String name;
    private List<Student> students;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<Student> getStudents() {
        return students;
    }

    public void setStudents(List<Student> students) {
        this.students = students;
    }

    @Override
    public String toString() {
        return "School{" +
                "name='" + name + ''' +
                ", students=" + students +
                '}';
    }
}

1.自己实现一个拷贝的工具类。

要拷贝的类必须实现Serializable接口。

工具类如下:

package clonePackage;

import java.io.*;

public class DeepCopyUtil {

    public static <T> T deepClone(T obj) {
        T cloneObj = null;
        try {
            //写入字节流
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ObjectOutputStream obs = new ObjectOutputStream(out);
            obs.writeObject(obj);
            obs.close();

            //分配内存,写入原始对象,生成新对象
            ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(ios);
            //返回生成的新对象
            cloneObj = (T) ois.readObject();
            ois.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cloneObj;
    }
}

测试代码:

@Test
    public void test() {
        School school = new School();
        school.setName("西安第一小学");
        Student student = new Student();
        student.setAge(10);
        student.setId("1");
        List<Student> students = new ArrayList<>();
        students.add(student);
        school.setStudents(students);
        // 开始克隆
        School clone = DeepCopyUtil.deepClone(school);
        System.out.println("修改前:");
        System.out.println("school:" + school);
        System.out.println("clone:" + clone);
        System.out.println("----------------------------------------------------------------");
        clone.getStudents().get(0).setId("2");
        clone.getStudents().get(0).setAge(20);
        System.out.println("修改后:");
        System.out.println("student:" + school);
        System.out.println("clone:" + clone);
    }

测试结果:

修改前:
school:School{name='西安第一小学', students=[Student{id='1', age=10}]}
clone:School{name='西安第一小学', students=[Student{id='1', age=10}]}
------------------------------------------------------------------------
修改后:
school:School{name='西安第一小学', students=[Student{id='1', age=10}]}
clone:School{name='西安第一小学', students=[Student{id='2', age=20}]}

Process finished with exit code 0

2.使用SerializationUtils

要拷贝的类必须实现Serializable接口。

导入依赖

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.12.0</version>
        </dependency>

测试代码:

 @Test
    public void testSerializationUtils() {
        School school = new School();
        school.setName("西安第一小学");
        Student student = new Student();
        student.setAge(10);
        student.setId("1");
        List<Student> students = new ArrayList<>();
        students.add(student);
        school.setStudents(students);
        // 开始克隆
        School clone = SerializationUtils.clone(school);
        System.out.println("修改前:");
        System.out.println("school:" + school);
        System.out.println("clone:" + clone);
        System.out.println("-------------------------------------------------------------------");
        clone.getStudents().get(0).setId("2");
        clone.getStudents().get(0).setAge(20);
        System.out.println("修改后:");
        System.out.println("student:" + school);
        System.out.println("clone:" + clone);
    }

测试结果:

修改前:
school:School{name='西安第一小学', students=[Student{id='1', age=10}]}
clone:School{name='西安第一小学', students=[Student{id='1', age=10}]}
------------------------------------------------------------------------
修改后:
student:School{name='西安第一小学', students=[Student{id='1', age=10}]}
clone:School{name='西安第一小学', students=[Student{id='2', age=20}]}

Process finished with exit code 0

3.GSON

无需实现Serializable接口。

需导入依赖

        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.5</version>
        </dependency>

测试代码:

 @Test
    public void testGson() {
        School school = new School();
        school.setName("西安第一小学");
        Student student = new Student();
        student.setAge(10);
        student.setId("1");
        List<Student> students = new ArrayList<>();
        students.add(student);
        school.setStudents(students);
        // 开始克隆
        Gson gson = new Gson();
        School clone = gson.fromJson(gson.toJson(school), School.class);
        System.out.println("修改前:");
        System.out.println("school:" + school);
        System.out.println("clone:" + clone);
        System.out.println("----------------------------------------------------------------");
        clone.getStudents().get(0).setId("2");
        clone.getStudents().get(0).setAge(20);
        System.out.println("修改后:");
        System.out.println("student:" + school);
        System.out.println("clone:" + clone);
    }

测试结果:

修改前:
school:School{name='西安第一小学', students=[Student{id='1', age=10}]}
clone:School{name='西安第一小学', students=[Student{id='1', age=10}]}
------------------------------------------------------------------------
修改后:
student:School{name='西安第一小学', students=[Student{id='1', age=10}]}
clone:School{name='西安第一小学', students=[Student{id='2', age=20}]}

Process finished with exit code 0

4.Jackson

无需实现Serializable接口。

需导入依赖

<dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.9.0</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.0</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.9.0</version>
        </dependency>

测试代码:

@Test
    public void testjackson() throws IOException {
        School school = new School();
        school.setName("西安第一小学");
        Student student = new Student();
        student.setAge(10);
        student.setId("1");
        List<Student> students = new ArrayList<>();
        students.add(student);
        school.setStudents(students);
        // 开始克隆
        ObjectMapper mapper = new ObjectMapper();
        School clone = mapper.readValue(mapper.writeValueAsString(school), School.class);
        System.out.println("修改前:");
        System.out.println("school:" + school);
        System.out.println("clone:" + clone);
        System.out.println("----------------------------------------------------------------");
        clone.getStudents().get(0).setId("2");
        clone.getStudents().get(0).setAge(20);
        System.out.println("修改后:");
        System.out.println("student:" + school);
        System.out.println("clone:" + clone);
    }

测试结果:

修改前:
school:School{name='西安第一小学', students=[Student{id='1', age=10}]}
clone:School{name='西安第一小学', students=[Student{id='1', age=10}]}
------------------------------------------------------------------------
修改后:
student:School{name='西安第一小学', students=[Student{id='1', age=10}]}
clone:School{name='西安第一小学', students=[Student{id='2', age=20}]}

Process finished with exit code 0