• [Java]ArrayList的深拷贝与浅拷贝


    最近在刷Leetcode,里面经常用到ArrayList,对于ArrayList的拷贝也是弄得不是很明白。

    ArrayList的拷贝方法有很多,其中大部分都是浅拷贝,例如通过构造函数方法拷贝,

    1 List<Integer> l2 = new ArrayList<>(l1);

    或者addAll方法:

    1 List<Integer> l2 = new ArrayList<>();
    2 l2.addAll(l1);

    这些都是浅拷贝,其中clone()方式有些特殊,最开始我以为通过clone()是实现深拷贝,因为我看很多题解都是用这种方式进行拷贝。但其实clone()也是浅拷贝,原因如下:

    之所以题解经常用clone()或者构造方法直接进行复制,是因为做题通常是Interger或者String类型的List,Interger和String类型都是不可变类,那么只需要通过浅拷贝拷贝一层即可。

    而后,我看一些文章写深拷贝方法,其中有一个比较特殊。

    例如有一个Person类如下:

        static class Person implements Cloneable{
            int age;
            public Person(int age){this.age = age;}
            @Override
            protected Object clone() throws CloneNotSupportedException {
                return super.clone();
            }
        }

    通过以下代码,可以实现深拷贝;

    List<Person> l3 = new ArrayList<>();
    List<Person> l4 = new ArrayList<>();
    for (Person person:l3)
        l4.add((Person)person.clone());

    但是这样的说法不准确,这样的代码只是多拷贝了一层,如果Person类改成如下,这样的拷贝就不成立了。

    static class Person implements Cloneable{
        int a;
        Age age;
        public Person(int a){this.a = a;}
        @Override
        protected Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    }

    虽然完成了对Person的拷贝,改变person2的属性值不会影响到person1,但是person1和person2引用的Age对象是同一个,也就是没有实现深拷贝。

    后来发现,在实际场景中,在代码逻辑层面想要完全实现深拷贝非常困难,因为难免会碰到有一些类套娃套了很多层。于是经过继续看一些文章,发现使用序列化方法可以实现深拷贝。

    这段代码来自其他文章

     1     public static <T> List<T> deepCopy(List<T> src) throws IOException, ClassNotFoundException {
     2         ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
     3         ObjectOutputStream out = new ObjectOutputStream(byteOut);
     4         out.writeObject(src);
     5 
     6         ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
     7         ObjectInputStream in = new ObjectInputStream(byteIn);
     8 
     9         List<T> copy_list = (List<T>) in.readObject();
    10         return copy_list;
    11     }

    所有需要拷贝到的对象,通通要实现Serializable

    static class Person implements Serializable
    static class Age implements Serializable
  • 相关阅读:
    从Dojo1.6到Dojo1.8(二)—— 基本模块,事件,约定,DOM操作
    从Dojo1.6到Dojo1.8(三)—— Parser,Dijit,DojoX
    在Node.js上使用dojo库进行面向对象web应用开发
    JavaScript事件代理和委托(Delegation)
    介绍一款神级API接口神器,高效工作,告别加班!
    sqlserver备份存储过程
    WSGI原理与简单实现
    从Python看Web架构的发展
    Celery:小试牛刀
    Flask:用户角色与权限管理
  • 原文地址:https://www.cnblogs.com/liusandao/p/12345208.html
Copyright © 2020-2023  润新知