1. 程式人生 > 其它 >java:陣列拷貝與“擴容”

java:陣列拷貝與“擴容”

技術標籤:java知識相關java

1、前述

java裡面,陣列的“擴容”與“拷貝”,藉助“拷貝”實現“動態陣列”
java裡面的陣列 int arr[]= new int[10]; arr在棧上 new出來的東西在堆上
所謂的陣列的擴容,其實是物件所指向的記憶體發生了變化,導致陣列“看起來長度變化”,並不是真正意義上的“動態陣列”

拷貝前後,記憶體分離 深拷貝
反之,淺拷貝

2、實現

1、new一個新array

        //way 1 new一個新array
        int arr[] = new int[]{1,2,3,4,5,6,7,8,9,10};
        int brr [] = new int[arr.length*2];
        for(int i = 0;i<arr.length;i++){
            brr[i] = arr[i];
        }
        arr = brr;
        System.out.println("brr = arr"+Arrays.toString(arr));
        if (arr==brr)
            System.out.println("共用地址");
        else
            System.out.println("地址不同");
2 Object類的 clone方法  克隆,並不會改變長度
        //way2 clone方法  克隆,並不會改變長度
        int crr[] = new int[]{1,2,3,4,5,6,7,8,9,10};
        int drr[] =crr.clone();
        System.out.println("clone"+Arrays.toString(drr));
        if (crr==drr)
            System.out.println("共用地址");
        else
            System.out.println("地址不同");
        //Object 類的clone方法 該方法是類 Object 中的方法,可以建立一個有單獨記憶體空間的對像。故而是地址不同的

3、Arrays.copyOf()方法 底層實現是System.arrayCopy()

        int err[]= new int[]{1,2,3,4,5,6,7,8,9,10};
        int frr[]=Arrays.copyOf(err,err.length*2);
        System.out.println("Arrays.copyOf"+Arrays.toString(frr));
        if (err==frr)
            System.out.println("共用地址");
        else
            System.out.println("地址不同");
        /* Arrays.copyOf()底層實現,是 System.ArrayCopy()方法
        //其機制是先new一個newLength的copy陣列,藉助System.ArrayCopy()把老陣列內容拷貝到新陣列,最後返回新陣列
        //所以,是new了一塊地址 當然記憶體是不同的
        原始碼實現
        copyOf(int[] original, int newLength) {
        int[] copy = new int[newLength];
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
         }
        * */

4、System.ArrayCopy() native方法 ,看不了實現

        int grr[] = new int[]{1,2,3,4,5,6,7,8,9,10};
        int hrr[] = new int[10];
        //方法的src dest陣列必須非空 必須宣告空間 不然報錯
        System.arraycopy(grr,0,hrr,0,grr.length);
        System.out.println("System.Arraycopy"+Arrays.toString(hrr));
        if (grr==hrr)
            System.out.println("共用地址");
        else
            System.out.println("地址不同");
        //System.ArrayCopy() 是native方法,無法檢視其原始碼

5、淺拷貝的一種實現

        int irr[] = new int[]{1,2,3,4,5,6,7,8,9,10};
        int jrr[] = irr;
        System.out.println(" int jrr[] = irr;"+Arrays.toString(hrr));
        if (irr==jrr)
            System.out.println("共用地址");
        else
            System.out.println("地址不同");
        //其實這和way1是一樣的,way1是new了塊新記憶體,但原來的陣列指向了新的記憶體 記憶體是有共用的
        //這塊,是新陣列沒有new出地址,直接指向老陣列的地址
上面幾個方法,對於一維陣列是深度拷貝,即記憶體分離。但對於二維陣列或n維,
可以理解為定義了一個二維陣列,記憶體在堆中開闢,其中一維是共享地址的,另一維是記憶體獨立的,屬於淺拷貝。
可以通過迴圈,實現記憶體分離的深度拷貝