當前位置: 妍妍網 > 碼農

Java List復制:淺拷貝與深拷貝方法及區別

2024-05-14碼農

List淺拷貝

眾所周知,list本質上是陣列,而陣列的是以地址的形式進行儲存。

如上圖將list A淺拷貝給list B,由於進行的是淺拷貝,所以直接將A的內容復制給了B,java中相同內容的陣列指向同一地址,即進行淺拷貝後A與B指向同一地址。造成的後果就是,改變B的同時也會改變A,因為改變B就是改變B所指向地址的內容,由於A也指向同一地址,所以A與B一起改變。

幾種淺拷貝

  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);

    測試及結果

    printList(destList); //打印未改變B之前的A 
    srcList.get(0).setAge(100);//改變B
    printList(destList); //打印改變B後的A
    //打印結果
    123-->20
    ABC-->21
    abc-->22
    123-->100
    ABC-->21
    abc-->22

List深拷貝

如圖,深拷貝就是將A復制給B的同時,給B建立新的地址,再將地址A的內容傳遞到地址B。ListA與ListB內容一致,但是由於所指向的地址不同,所以改變相互不受影響。

最近整理了一份最新的面試資料,裏面收錄了2021年各個大廠的面試題,打算跳槽的小夥伴不要錯過,關註公眾號後端面試那些事,回復:2022面經,即可獲取

深拷貝的方法

  1. 使用序列化方法

    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;
    }
    List<Person> destList=deepCopy(srcList); //呼叫該方法

  2. clone方法

    public class A implements Cloneable {
    public String name[];
    public A(){
    name=new String[2];
    }
    public Object clone() {
    A o = null;
    try {
    o = (A) super.clone();
    } catch (CloneNotSupportedException e) {
    e.printStackTrace();
    }
    return o;
    }
    }
    for(int i=0;i<n;i+=){
    copy.add((A)src.get(i).clone());
    }

Java對物件和基本的數據型別的處理是不一樣的。在Java中用物件的作為入口參數的傳遞則缺省為」參照傳遞」,也就是說僅僅傳遞了物件的一個」參照」,這個」參照」的概念同C語言中的指標參照是一樣的。當函式體內部對輸入變量改變時,實質上就是在對這個物件的直接操作。

除了在函式傳值的時候是」參照傳遞」,在任何用」=」向物件變量賦值的時候都是」參照傳遞」。

測試及結果

printList(destList); //打印未改變B之前的A 
srcList.get(0).setAge(100);//改變B
printList(destList); //打印改變B後的A
123-->20
ABC-->21
abc-->22
123-->20
ABC-->21
abc-->22

在淺復制的情況下,源數據被修改破壞之後,使用相同參照指向該數據的目標集合中的對應元素也就發生了相同的變化。因此,在需求要求必須深復制的情況下,要是使用上面提到的方法,請確保List中的T類物件是不易被外部修改和破壞的。

來源:blog.csdn.net/demonliuhui/

article/details/54572908

>>

END

精品資料,超贊福利,免費領

微信掃碼/長按辨識 添加【技術交流群

群內每天分享精品學習資料

最近開發整理了一個用於速刷面試題的小程式;其中收錄了上千道常見面試題及答案(包含基礎並行JVMMySQLRedisSpringSpringMVCSpringBootSpringCloud訊息佇列等多個型別),歡迎您的使用。

👇👇

👇點選"閱讀原文",獲取更多資料(持續更新中