1. 程式人生 > >【效率優化專題】2.java陣列拷貝的3種方式和效率對比

【效率優化專題】2.java陣列拷貝的3種方式和效率對比

Java語言中常用的陣列拷貝方式有:for迴圈拷貝,通過Arrays.copyOf()方法,System.arraycopy和clone()方法拷貝。

1 測試場景

我們用最簡單的整數陣列來測試。首先建立一個整型陣列,並且初始化資料。然後分別用這3種方式來拷貝陣列同樣的次數。來測分別試這三種情況的效率。

1.1 初始化陣列

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

1.1 for迴圈拷貝陣列

採用for迴圈遍歷陣列,然後根據陣列下標對應賦值,來實現複製陣列。

/** 1 for 迴圈拷貝*/int
[] arr1 =newint[len];for(int i =0; i < len; i++){ arr1[i]= arr0[i];}

1.2 Arrays.copyOf拷貝陣列

java.util.Arrays類中提供了一個copyOf()方法,通過這個方法可以實現陣列複製。這個方法的原理是內部建立了一個數組物件,然後通過System.arraycopy來實現陣列複製.

  • copyOf方法原始碼
publicstaticint[] copyOf(int[] original,int newLength){int[] copy =newint[newLength];System.arraycopy
(original,0, copy,0,Math.min(original.length, newLength));return copy;}
  • System.arraycopy原始碼

System.arraycop方法是通過native方法,Java虛擬機器內部實現的。

publicstaticnativevoid 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 =newint[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.
 */publicclassDemo1{publicstaticvoid main(String[] args){/** 初始化陣列*/int len =1000;int count =10000000;int[] arr0 =newint[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 =newint[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 =newint[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));}}

輸出結果:

1for迴圈複製:44512Arrays.copyOf複製陣列:64743System.arraycopy複製陣列:64394Object.clone()複製陣列:*6436

這個輸出結果根據電腦和執行環境,可能會不一致。從這個輸出可以看出:

for迴圈遍歷陣列複製的方式用時最小.比其他3中少了50%左右的時間。

  • 其他不變,只將迴圈次數改為一百萬次的輸出結果
1for迴圈複製:6402Arrays.copyOf複製陣列:8283System.arraycopy複製陣列:6434Object.clone()複製陣列:*645

這個差距就很小了。

  • 其他不變,迴圈次數改為一千萬次的輸出結果,初始陣列的長度100的輸出結果
1for迴圈複製:9482Arrays.copyOf複製陣列:7093System.arraycopy複製陣列:6594Object.clone()複製陣列:*666

這個差距也不大。反而是for迴圈遍歷耗時最多。

  • 其他不變,迴圈次數改為一千萬次的輸出結果,初始陣列的長度10的輸出結果
1for迴圈複製:2502Arrays.copyOf複製陣列:1273System.arraycopy複製陣列:1574Object.clone()複製陣列:*193

在陣列長度為10的時候,for迴圈遍歷賦值耗時要超過其他3種方式。

  • 其他不變,迴圈次數改為一百萬次,初始陣列的長度10000的輸出結果
1for迴圈複製:58512Arrays.copyOf複製陣列:64713System.arraycopy複製陣列:64434Object.clone()複製陣列:6485

這個輸出結果差不多。

3 結論

通過上述測試程式碼的輸出資料,可以簡單分析一下,當陣列長度超過一定值的時候(測試程式碼中,長度改為1000,這個值不精確),for迴圈遍歷賦值,效率會略高出其他3種方式。

另外在執行次數長的時候(測試程式碼改為執行1千萬次,陣列長度1000)的時候,for迴圈遍歷賦值效率最高,而且優勢明顯(快50%左右)。陣列長度改為100,就沒那麼明顯了。

System.arraycopy提供了擷取陣列中的一部分來生成新的陣列,這個功能很方便。(也可以用for迴圈遍歷來實現)。

Arrays.copyOf()和clone()方法可以複製整個陣列,在陣列長度比較短的時候,程式碼比較簡介,推薦採用。