首页 > java > profile > 2.java数组拷贝的3种方式和效率对比

2.java数组拷贝的3种方式和效率对比

Java语言中常用的数组拷贝方式有:for循环拷贝,通过Arrays.copyOf()方法,System.arraycopy和clone()方法拷贝。

1 测试场景

我们用最简单的整数数组来测试。首先创建一个整型数组,并且初始化数据。然后分别用这3种方式来拷贝数组同样的次数。来测分别试这三种情况的效率。

1.1 初始化数组

int len = 1000;
int[] arr0 = new int[len];
for (int i = 0; i < len; i++) {
    arr0[i] = i;
}

1.1 for循环拷贝数组

采用for循环遍历数组,然后根据数组下标对应赋值,来实现复制数组。

/** 1 for 循环拷贝*/
int[] arr1 = new int[len];
for (int i = 0; i < len; i++) {
    arr1[i] = arr0[i];
}

1.2 Arrays.copyOf拷贝数组

java.util.Arrays类中提供了一个copyOf()方法,通过这个方法可以实现数组复制。这个方法的原理是内部创建了一个数组对象,然后通过System.arraycopy来实现数组复制.

  • copyOf方法源码
public static int[] copyOf(int[] original, int newLength) {
    int[] copy = new int[newLength];
    System.arraycopy(original, 0, copy, 0,
                     Math.min(original.length, newLength));
    return copy;
}
  • System.arraycopy源码

System.arraycop方法是通过native方法,Java虚拟机内部实现的。

public static native void arraycopy(Object src,  int  srcPos,
                                    Object dest, int destPos,
                                    int length);
  • 调用Arrays.copyOf()方法
int[] arr2 = Arrays.copyOf(arr0, arr0.length);

1.3 System.arraycopy复制数组

System.arraycopy方法提供了从数组中截取一部分,生成一个新的数组,也是Arrays.copyOf()方法的底层实现。

int[] arr3 = new int[len];
System.arraycopy(arr0, 0, arr3, 0, arr0.length);

1.4 clone()方法拷贝数组

Java的Object

int[] arr3 = arr0.clone();

2 测试这几种复制方法

将上述4中复制方式,对一个长度1000的数组,复制一千万次,来看一下执行时间。

2.1 示例代码

package com.dashidan.profile1;

import java.util.Arrays;

/**
 * 大屎蛋教程网-dashidan.com
 * 2.java数组复制的3种方式和效率对比
 *
 * Created by 大屎蛋 on 2018/5/23.
 */
public class Demo1 {

    public static void main(String[] args) {
        /** 初始化数组*/
        int len = 1000;
        int count = 10000000;
        int[] arr0 = new int[len];
        for (int i = 0; i < len; i++) {
            arr0[i] = i;
        }

        long t1 = System.currentTimeMillis();

        for (int c = 0; c < count; c++) {
            /** 1 for 循环复制*/
            int[] arr1 = new int[len];
            for (int i = 0; i < len; i++) {
                arr1[i] = arr0[i];
            }
        }

        long t2 = System.currentTimeMillis();

        /** 2 Arrays.copyOf复制数组*/
        for (int c = 0; c < count; c++) {
            int[] arr2 = Arrays.copyOf(arr0, arr0.length);
        }

        long t3 = System.currentTimeMillis();

        /** 3 System.arraycopy复制数组*/
        for (int c = 0; c < count; c++) {
            int[] arr3 = new int[len];
            System.arraycopy(arr0, 0, arr3, 0, arr0.length);
        }

        long t4 = System.currentTimeMillis();
        /** 4 Object.clone() 复制数组*/
        for (int c = 0; c < count; c++) {
            int[] arr4 = arr0.clone();
        }

        long t5 = System.currentTimeMillis();

        System.out.println("1 for 循环复制: " + (t2 - t1));
        System.out.println("2 Arrays.copyOf复制数组:  " + (t3 - t2));
        System.out.println("3 System.arraycopy复制数组:  " + (t4 - t3));
        System.out.println("4 Object.clone() 复制数组: * " + (t5 - t4));
    }
}

输出结果:

1 for 循环复制: 4451
2 Arrays.copyOf复制数组:  6474
3 System.arraycopy复制数组:  6439
4 Object.clone() 复制数组: * 6436

这个输出结果根据电脑和运行环境,可能会不一致。从这个输出可以看出:

for循环遍历数组复制的方式用时最小.比其他3中少了50%左右的时间。

  • 其他不变,只将循环次数改为一百万次的输出结果
1 for 循环复制: 640
2 Arrays.copyOf复制数组:  828
3 System.arraycopy复制数组:  643
4 Object.clone() 复制数组: * 645

这个差距就很小了。

  • 其他不变,循环次数改为一千万次的输出结果,初始数组的长度100的输出结果
1 for 循环复制: 948
2 Arrays.copyOf复制数组:  709
3 System.arraycopy复制数组:  659
4 Object.clone() 复制数组: * 666

这个差距也不大。反而是for循环遍历耗时最多。

  • 其他不变,循环次数改为一千万次的输出结果,初始数组的长度10的输出结果
1 for 循环复制: 250
2 Arrays.copyOf复制数组:  127
3 System.arraycopy复制数组:  157
4 Object.clone() 复制数组: * 193

在数组长度为10的时候,for循环遍历赋值耗时要超过其他3种方式。

  • 其他不变,循环次数改为一百万次,初始数组的长度10000的输出结果
1 for 循环复制: 5851
2 Arrays.copyOf复制数组:  6471
3 System.arraycopy复制数组:  6443
4 Object.clone() 复制数组:  6485

这个输出结果差不多。

3 结论

通过上述测试代码的输出数据,可以简单分析一下,当数组长度超过一定值的时候(测试代码中,长度改为1000,这个值不精确),for循环遍历赋值,效率会略高出其他3种方式。

另外在运行次数长的时候(测试代码改为运行1千万次,数组长度1000)的时候,for循环遍历赋值效率最高,而且优势明显(快50%左右)。数组长度改为100,就没那么明显了。

System.arraycopy提供了截取数组中的一部分来生成新的数组,这个功能很方便。(也可以用for循环遍历来实现)。

Arrays.copyOf()和clone()方法可以复制整个数组,在数组长度比较短的时候,代码比较简介,推荐采用。

转载请保留原文链接.