数组拷贝

java数组声明的三种方式

①:声明并初始化
数据类型[] 数组名 = {值,值,...};

String[] strArray = {"zhu","xue","rong"};

②:声明后赋值
数据类型[] 数组名 = new 数据类型[数组长度];

String[] strArray = new String[5];
strArray[0] = "zhu";
strArray[1] = "xue";
strArray[4] = "rong";

数据类型[] 数组名=new 数据类型[]{值,值,...};

String[] strArray = new String[]{"zhu","xue","rong"};

java浅拷贝与深拷贝

浅拷贝:在堆内存中不会分配新的空间,而是增加一个引用变量和之前的引用指向相同的堆空间。

详释:
①对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递,也就是将该属性值复制一份给新的对象。因为是两份不同的数据,所以对其中一个对象的该成员变量值进行修改,不会影响另一个对象拷贝得到的数据。
②对于数据类型是引用数据类型的成员变量,比如说成员变量是某个数组、某个类的对象等,那么浅拷贝会进行引用传递,也就是只是将该成员变量的引用值(内存地址)复制一份给新的对象。因为实际上两个对象的该成员变量都指向同一个实例。在这种情况下,在一个对象中修改该成员变量会影响到另一个对象的该成员变量值。

深拷贝:在堆内存中分配新空间,将之前的数组堆内存中的内容拷贝到新的空间中。

详释:
对于深拷贝来说,不仅要复制对象的所有基本数据类型的成员变量值,还要为所有引用数据类型的成员变量申请存储空间,并复制每个引用数据类型成员变量所引用的对象,直到该对象可达的所有对象。也就是说,对象进行深拷贝要对整个对象图进行拷贝!

注意
基本数据类型是值传递,所以修改值后不会影响另一个对象的该属性值;

引用数据类型是地址传递(引用传递),所以修改值后另一个对象的该属性值会同步被修改。

String类型非常特殊,首先,String类型属于引用数据类型,不属于基本数据类型,但是String类型的数据是存放在常量池中的,也就是无法修改的!


java数组拷贝的四种方式

壹:for循环拷贝

贰:Object.clone()方法

从源码来看是 native 方法,所以是调用了 C 或者 C++ 代码。

protected native Object clone() throws CloneNotSupportedException;

叁:System.arraycopy()方法

public static native void arraycopy(Object src,  int  srcPos,
                                        Object dest, int destPos,
                                        int length);
//src :源数组; srcPos:源数组要复制的起始位置;
//dest:目的数组;   destPos:目的数组放置的起始位置;  length:复制的长度.

目的数组大小可能小于源数组,所以可以使用Math.min(src.length, dest.length)取两者小值

肆:Arrays.copyOf()方法

String[] arr= {"zz", "xx", "rr", "aa", "bb"};
String[] destArr = Arrays.copyOf(arr, arr.length);

看源码,它的实现还是基于 System.arraycopy(),所以效率自然低于 System.arraycpoy()。

public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
    @SuppressWarnings("unchecked")
    T[] copy = ((Object)newType == (Object)Object[].class)
        ? (T[]) new Object[newLength]
        : (T[]) Array.newInstance(newType.getComponentType(), newLength);
    System.arraycopy(original, 0, copy, 0,
                     Math.min(original.length, newLength));
    return copy;
}
//该方法对应不同的数据类型都有各自的重载方法
//original - 要复制的数组
//newLength - 要返回的副本的长度
//newType - 要返回的副本的类型

此四种拷贝对于基本类型来说,为深拷贝,源数组与目的数组的改变是相互独立的,互不影响;对于引用类型来说,只是拷贝了地址,为浅拷贝彼此的更改相互影响


    public static void main(String[] args) {
        test1();
        test2();
        test3();
    }

    static class inArrayTest {
        private int val = 10;

        public int getVal() {
            return val;
        }

        public void setVal(int val) {
            this.val = val;
        }

    }

    public static void show(inArrayTest[] array) {
        for (int i = 0; i < array.length; i++) {
            System.out.print(array[i].getVal() + " ");
        }
        System.out.println();
    }

    public static void test3() {

        inArrayTest[] arr = new inArrayTest[3];
        arr[0] = new inArrayTest();
        arr[1] = new inArrayTest();
        arr[2] = new inArrayTest();

        //对于引用类型数组用for循环拷贝为深拷贝
        inArrayTest[] forCopyArr = new inArrayTest[3];
        for (int i = 0; i < arr.length; i++) {
            forCopyArr[i] = arr[i];
        }
        arr[1].setVal(100);
        forCopyArr[0].setVal(1000);
        show(arr);
        show(forCopyArr);

        //Object.clone() 引用类型为深拷贝
        inArrayTest[] cloneArr = arr.clone();
        arr[1].setVal(200);
        cloneArr[0].setVal(2000);
        show(arr);
        show(cloneArr);

        //System.arraycopy() 引用类型为深拷贝
        inArrayTest[] sysArr = new inArrayTest[3];
        System.arraycopy(arr, 0, sysArr, 0, arr.length);
        arr[1].setVal(300);
        sysArr[0].setVal(3000);
        show(arr);
        show(sysArr);

        //Arrays.copyOf() 引用类型为深拷贝
        inArrayTest[] coArr = Arrays.copyOf(arr, arr.length);
        arr[1].setVal(400);
        coArr[0].setVal(4000);
        show(arr);
        show(coArr);
    }

    public static void test2() {
        //for拷贝 String类型为浅拷贝
        String[] forArr = {"zz", "xx", "rr", "aa", "bb"};
        String[] forCopyArr = new String[forArr.length];
        for (int i = 0; i < forCopyArr.length; i++) {
            forCopyArr[i] = forArr[i];
        }
        forArr[2] = "rrr";
        forCopyArr[2] = "RRR";
        System.out.println(Arrays.toString(forArr));
        System.out.println(Arrays.toString(forCopyArr));

        //Object.clone() String类型为浅拷贝
        String[] cloneArr = {"zz", "xx", "rr", "aa", "bb"};
        String[] cloneCopyArr = cloneArr.clone();
        cloneArr[2] = "rrr";
        cloneCopyArr[2] = "RRR";
        System.out.println(Arrays.toString(cloneArr));
        System.out.println(Arrays.toString(cloneCopyArr));

        //System.arraycopy() String类型为浅拷贝
        String[] sysArr = {"zz", "xx", "rr", "aa", "bb"};
        String[] sysCopyArr = new String[sysArr.length];
        System.arraycopy(sysArr, 0, sysCopyArr, 0, sysArr.length);
        sysArr[2] = "rrr";
        sysCopyArr[2] = "RRR";
        System.out.println(Arrays.toString(sysArr));
        System.out.println(Arrays.toString(sysCopyArr));

        //Arrays.copyOf() String类型为浅拷贝
        String[] coArr = {"zz", "xx", "rr", "aa", "bb"};
        String[] coCopyArr = Arrays.copyOf(coArr, coArr.length);
        coArr[2] = "rrr";
        coCopyArr[2] = "RRR";
        System.out.println(Arrays.toString(coArr));
        System.out.println(Arrays.toString(coCopyArr));

    }


    public static void test1() {
        //for拷贝 基本类型为浅拷贝
        int[] forArr = {1, 2, 3, 4, 5};
        int[] forCopyArr = new int[forArr.length];
        for (int i = 0; i < forCopyArr.length; i++) {
            forCopyArr[i] = forArr[i];
        }
        forArr[2] = 300;
        forCopyArr[2] = 3000;
        System.out.println(Arrays.toString(forArr));
        System.out.println(Arrays.toString(forCopyArr));

        //Object.clone() 基本类型为浅拷贝
        int[] cloneArr = {1, 2, 3, 4, 5};
        int[] cloneCopyArr = cloneArr.clone();
        cloneArr[2] = 300;
        cloneCopyArr[2] = 3000;
        System.out.println(Arrays.toString(cloneArr));
        System.out.println(Arrays.toString(cloneCopyArr));

        //System.arraycopy() 基本类型为浅拷贝
        int[] sysArr = {1, 2, 3, 4, 5};
        int[] sysCopyArr = new int[sysArr.length];
        System.arraycopy(sysArr, 0, sysCopyArr, 0, sysArr.length);
        sysArr[2] = 300;
        sysCopyArr[2] = 3000;
        System.out.println(Arrays.toString(sysArr));
        System.out.println(Arrays.toString(sysCopyArr));

        //Arrays.copyOf() 基本类型为浅拷贝
        int[] coArr = {1, 2, 3, 4, 5};
        int[] coCopyArr;
        coCopyArr = Arrays.copyOf(coArr, coArr.length);
        coArr[2] = 300;
        coCopyArr[2] = 3000;
        System.out.println(Arrays.toString(coArr));
        System.out.println(Arrays.toString(coCopyArr));

    }

方法性能测试比较

import java.util.Arrays;
import java.util.Random;

/**
 * 数组复制的方法比较
 *
 * @author TinyDolphin
 *         2017/11/1 15:40.
 */
public class Main {
    public static void main(String[] args) {
        // int length = 10000000;    // 千万级别
        int length = 8000000;        // 百万级别
        Integer[] arr = new Integer[length];
        Integer[] arr2 = new Integer[length];
        for (int index = 0; index < length; index++) {
            arr[index] = new Random().nextInt(length) + 1;
        }

        // for() 循环方法
        long start = System.currentTimeMillis();
        for (int index = 0; index < length; index++) {
            arr2[index] = arr[index];
        }
        long end = System.currentTimeMillis();
        System.out.println("for()循环方法耗费时间:" + (end - start) + "ms");

        // Object.clone() 方法
        start = System.currentTimeMillis();
        arr2 = arr.clone();
        end = System.currentTimeMillis();
        System.out.println("Object.clone()方法耗费时间:" + (end - start) + "ms");

        // Arrays.copyOf() 方法
        start = System.currentTimeMillis();
        arr2 = Arrays.copyOf(arr, length);
        end = System.currentTimeMillis();
        System.out.println("Arrays.copyOf()方法耗费时间:" + (end - start) + "ms");

        // System.arraycopy() 方法
        start = System.currentTimeMillis();
        System.arraycopy(arr, 0, arr2, 0, length);
        end = System.currentTimeMillis();
        System.out.println("System.arraycopy()方法耗费时间:" + (end - start) + "ms");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值