java的system.arraycopy()方法


java.lang.System的靜態方法arraycopy()可以實現數組的復制,講課的老師說這個方法效率比較高,如果數組有成千上萬個元素,那么用這個方法,比用for語句循環快不少。於是我試了試,發現以下問題。 

如果是復制一個一位數組,那么改變復制后的數組並不影響原數組。但是如果復制一個二維數組,那么改變其中任何一個數組,那么另一個的值也發生了變化。開始不是很明白,后來上網查了查資料,理解了其中奧妙。 

java其實沒有二維數組的概念,平常實現的二維數組只是元素是一維數組的一維數組,而數組也是引用類型,繼承自Object類。數組是new出來的。這些性質也就導致arraycopy()二維數組時出現的問題。 

如果是一維數組,那么元素都是基礎類型(如int,double等),使用arraycopy()方法后,是把原數組的值傳給了新數組,屬於值傳遞。而如果是二維數組,數組的第一維裝的是一個一維數組的引用,第二維里是元素數值。對二維數組應用arraycopy()方法后,第一維的引用被復制給新數組的第一維,也就是兩個數組的第一維都指向相同的“那些數組”。而這時改變其中任何一個數組的元素的值,其實都修改了“那些數組”的元素的值,所以原數組和新數組的元素值都一樣了。 

OK,就是這樣。 

不明白可以看看這個例子: 

Java代碼   收藏代碼
  1. public class TestArrayCopy {  
  2.   
  3. /** 
  4. * @param args 
  5. */  
  6. public static void main(String[] args) {  
  7.    // TODO 自動生成方法存根  
  8.     
  9.    String[] s1 = {"中國","山西","太原","TYUT","zyy","加拿大","不知道哪個州","不知道哪個市","不知道哪個學校","yxf"};  
  10.    String[] s2 = new String[10];  
  11.    System.arraycopy(s1, 0, s2, 0, 10);  
  12.    s2[6] = "假設蒙大拿州";  
  13.    s2[7] = "假設蒙特利爾市";  
  14.    s2[8] = "假設Montreal商學院";  
  15.     
  16.    System.out.println("This is s1");  
  17.    for(int i = 0;i < s1.length ;i++){  
  18.     System.out.print(s1[i] + ",");  
  19.    }  
  20.     
  21.    System.out.println("\nThis is s2");  
  22.    for(int i = 0;i < s2.length ;i++){  
  23.     System.out.print(s2[i] + ",");  
  24.    }  
  25.     
  26.    String[][] s3 = {{"中國","山西","太原","TYUT","zyy"},{"加拿大","不知道哪個州","不知道哪個市","不知道哪個學校","yxf"}};  
  27.    String[][] s4 = new String[s3.length][s3[0].length];  
  28.    System.arraycopy(s3, 0, s4, 0, s3.length);  
  29.     
  30.    System.out.println("\nThis is original s3");  
  31.    for(int i = 0;i < s3.length ;i++){  
  32.     for(int j = 0; j< s3[0].length ;j++){  
  33.      System.out.print(s3[i][j] + ",");  
  34.     }  
  35.    }  
  36.     
  37.    s4[1][1] = "假設蒙大拿州";  
  38.    s4[1][2] = "假設蒙特利爾市";  
  39.    s4[1][3] = "假設Montreal商學院";  
  40.     
  41.    System.out.println("\nThis is s3 after s4 has changed.");  
  42.    for(int i = 0;i < s3.length ;i++){  
  43.     for(int j = 0; j< s3[0].length ;j++){  
  44.      System.out.print(s3[i][j] + ",");  
  45.     }  
  46.    }  
  47.     
  48.    System.out.println("\nThis is s4");  
  49.    for(int i = 0;i < s4.length ;i++){  
  50.     for(int j = 0; j < s4[0].length ; j++){  
  51.      System.out.print(s4[i][j] + ",");  
  52.     }  
  53.         
  54.    }  
  55. }  
  56.   
  57. }  


結果: 

This is s1 
中國,山西,太原,TYUT,zyy,加拿大,不知道哪個州,不知道哪個市,不知道哪個學校,yxf, 
This is s2 
中國,山西,太原,TYUT,zyy,加拿大,假設蒙大拿州,假設蒙特利爾市,假設Montreal商學院,yxf, 
This is original s3 
中國,山西,太原,TYUT,zyy,加拿大,不知道哪個州,不知道哪個市,不知道哪個學校,yxf, 
This is s3 after s4 has changed. 
中國,山西,太原,TYUT,zyy,加拿大,假設蒙大拿州,假設蒙特利爾市,假設Montreal商學院,yxf, 
This is s4 
中國,山西,太原,TYUT,zyy,加拿大,假設蒙大拿州,假設蒙特利爾市,假設Montreal商學院,yxf, 

arraycopy的實現方法: 
其中 Arrays.copy是JDK1.6中引用的新方法。它調用了System.arraycopy完成相關數組的復制。 
在JDK1.6中ArrayList的相關add remove等操作都是調用System.arraycopy來對其底層的Object[]elementData數組進行操作的。 
LinkedList則使用一個Entry的內部類,其有指向next和previous的引用保存元素,它的遍歷則先計算出所需index和size>>1(以為后的大小),確定是通過previous還是next遍歷。 
System.arraycopy 

Java代碼   收藏代碼
  1. 01.public static void arraycopy(Object src,       
  2. 02.                             int srcPos,       
  3. 03.                             Object dest,       
  4. 04.                             int destPos,       
  5. 05.                             int length)       
  6. 06.    從指定源數組中復制一個數組,復制從指定的位置開始,到目標數組的指定位置結束。從 src 引用的源數組到 dest 引用的目標數組,數組組件的一個子序列被復制下來。被復制的組件的編號等於 length 參數。源數組中位置在 srcPos 到 srcPos+length-1 之間的組件被分別復制到目標數組中的 destPos 到 destPos+length-1 位置。    


它是個native方法,測試結果表明, 

當數組很小,但存是調用次數多的話。 

使用它復制數組並不比for循環手工復制數組快。 
但是如果是數組比較大,那么使用System.arraycopy會比較有優勢,因為其使用的是內存復制,省去了大量的數組尋址訪問等時間。 
     native方法: 
Java不是完美的,Java的不足除了體現在運行速度上要比傳統的C++慢許多之外,Java無法直接訪問到操作系統底層(如系統硬件等),為此Java使用native方法來擴展Java程序的功能。 

  可以將native方法比作Java程序同C程序的接口,其實現步驟: 

  1、在Java中聲明native()方法,然后編譯; 

  2、用javah產生一個.h文件; 

  3、寫一個.cpp文件實現native導出方法,其中需要包含第二步產生的.h文件(注意其中又包含了JDK帶的jni.h文件); 

  4、將第三步的.cpp文件編譯成動態鏈接庫文件; 

  5、在Java中用System.loadLibrary()方法加載第四步產生的動態鏈接庫文件,這個native()方法就可以在Java中被訪問了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM