欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

浅谈Java语言中List集合复制(浅克隆与深度克隆)

程序员文章站 2022-05-04 10:47:42
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}]


浅谈Java语言中List集合复制(浅克隆与深度克隆)

修改克隆集合中的值,源集合也随之发生了变化。


方式二:

 @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}]

浅谈Java语言中List集合复制(浅克隆与深度克隆)

修改克隆集合中的值,源集合也随之发生了变化。


方式三:

 @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}]


浅谈Java语言中List集合复制(浅克隆与深度克隆)


修改克隆集合中的值,源集合也随之发生了变化。


方式四:

 @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}]


浅谈Java语言中List集合复制(浅克隆与深度克隆)


修改克隆集合中的值,源集合也随之发生了变化。


方式五:

 @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}]

浅谈Java语言中List集合复制(浅克隆与深度克隆)


修改克隆集合中的值,源集合也随之发生了变化。


方式六:

 @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}]

浅谈Java语言中List集合复制(浅克隆与深度克隆)


修改克隆集合中的值,源集合也随之发生了变化。


方式七:

 @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}]

浅谈Java语言中List集合复制(浅克隆与深度克隆)

修改克隆集合中的值,源集合也随之发生了变化。


场景:  如果只是单纯的复制集合,以上几种方法都适用。如果修改克隆的集合的值,而又不影响源集合中的值,以上方法就不适用了。因为以上方法克隆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}] 

浅谈Java语言中List集合复制(浅克隆与深度克隆)


修改克隆后集合的元素,源集合对应的元素没有发生任何变化,这就实现了深度克隆集合,不相互影响。

本文地址:https://blog.csdn.net/jinchunzhao123/article/details/108025823