目录

浅拷贝

深拷贝

小结

后续

对象列表的深度复制

结果


开门见山的说,List的复制其实是很常见的,List其本质就是数组,而其存储的形式是地址

 

如图所示,将List 0列表复制时,其实相当于List0的内容复制给了List1,java中相同内容的数组指向同一地址,即进行浅拷贝后List0与List1指向同一地址。

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

这也就是List的浅拷贝,其常见的实现方式有如下几种:

浅拷贝

1、遍历循环复制

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

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

List<Person> destList=new ArrayList<Person>(srcList);

3、使用list.addAll()方法

List<Person> destList=new ArrayList<Person>(); 
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);  

深拷贝

 

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

import org.apache.commons.collections.CollectionUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CopyTest {

	public static void main(String[] args) {
		List<Integer> list = new ArrayList<>();
			for (int i = 0; i < 10; i++) {
			list.add(i);
		}
		//list深度拷贝
		List<Integer> newList = new ArrayList<>();
		CollectionUtils.addAll(newList, new Object[list.size()]);
		Collections.copy(newList, list);
		newList.set(0, 10);
		System.out.println("原list值:" + list);
		System.out.println("新list值:" + newList);
	}
}
结果:
原list值:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
新list值:[10, 1, 2, 3, 4, 5, 6, 7, 8, 9]

小结

Java对对象和基本的数据类型的处理是不一样的。在Java中用对象的作为入口参数的传递则缺省为”引用传递”,也就是说仅仅传递了对象的一个”引用”,这个”引用”的概念同C语言中的指针引用是一样的。当函数体内部对输入变量改变时,实质上就是在对这个对象的直接操作。 除了在函数传值的时候是”引用传递”,在任何用”=”向对象变量赋值的时候都是”引用传递”。

在浅复制的情况下,源数据被修改破坏之后,使用相同引用指向该数据的目标集合中的对应元素也就发生了相同的变化。因此,在需求要求必须深复制的情况下,要是使用上面提到的方法,请确保List中的T类对象是不易被外部修改和破坏的。

后续

对象列表的深度复制

package top.luxd.Test;

import org.apache.commons.collections.CollectionUtils;
import org.junit.Test;

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

public class CopyTest implements Serializable {

    public static void main(String[] args) {

        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            list.add(i);
        }

        //list深度拷贝
        List<Integer> newList = new ArrayList<>();
        CollectionUtils.addAll(newList, new Object[list.size()]);
        Collections.copy(newList, list);
        newList.set(0, 10);

        System.out.println("原list值:" + list);
        System.out.println("新list值:" + newList);

    }


    @Test
    public void test() throws IOException, ClassNotFoundException {
        UserTest user1 = new UserTest("小明", 18);
        UserTest user2 = new UserTest("小红", 16);
        List<UserTest> list = new ArrayList<>();
        list.add(user1);
        list.add(user2);
        System.out.println("原List:" + list);

        // 进行深度复制
//        List<UserTest> listNew = new ArrayList<>();
//        for (int i = 0; i < list.size(); i += 1) {
//            listNew.add((UserTest) list.get(i).clone());
//        }

        List<UserTest> listNew = deepCopy(list);

        System.out.println("对新list进行操作");
        for (UserTest userTest : listNew) {
            userTest.setAge(99);
        }

        System.out.println("原list" + list);
        System.out.println("新list" + listNew);


    }


    class UserTest implements Serializable {

        String id;
        int age;

        public UserTest(String id, int age) {
            this.id = id;
            this.age = age;
        }

        public UserTest() {
        }

        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 "UserTest{" +
                    "id='" + id + '\'' +
                    ", age=" + age +
                    '}';
        }
    }

    //关键代码 运行序列化和反序列化  进行深度拷贝
    public static <T> List<T> deepCopy(List<T> src) throws IOException, ClassNotFoundException {
        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;
    }


}

结果

1
2
3
4

原List:[UserTest{id='小明', age=18}, UserTest{id='小红', age=16}]
对新list进行操作
原list[UserTest{id='小明', age=18}, UserTest{id='小红', age=16}]
新list[UserTest{id='小明', age=99}, UserTest{id='小红', age=99}]

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐