当前位置: 移动技术网 > IT编程>开发语言>Java > 浅谈Java语言中List集合复制(浅克隆与深度克隆)

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

2020年08月17日  | 移动技术网IT编程  | 我要评论
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

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网