[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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM