1. 程式人生 > >陣列拷貝方法

陣列拷貝方法

陣列拷貝的方法有四種

分別為:for clone() System.arraycopy()Array.copyOf()
要研究陣列的拷貝,先看看淺拷貝與深拷貝的概念:
概括起來講,淺拷貝就是指兩個物件公用一個值,一個的改變了另一個也會隨之改變,深拷貝則是兩個物件雖然值相等,但是相互獨立互不影響。

1.for迴圈方法:

程式碼靈活,但效率低。

public class Arraycopy {
       public static void main(String[] args) {
         int[] array1 = new int[]{1, 2, 8, 7, 6};
         int[] array2 = new int[array1.length];
         for (int i = 0;i < array1.length;i++){
        array2[i] = array1[i];
}

        System.out.println("array1 = " + Arrays.toString(array1));
        System.out.println("array2 = " + Arrays.toString(array2));
        System.out.println("======================");

        array2[0] = 100;
        System.out.println("array1 = " + Arrays.toString(array1));
        System.out.println("array2 = " + Arrays.toString(array2));
   }
   }

在這裡插入圖片描述
由結果可以看出,當對複製陣列的某個元素進行改變時,並不影響被複制陣列對應元素,即對於基本資料型別來說for迴圈語句是深拷貝。

  package com.me;

  class TestArray {
private int val = 10;
public void setVal(int val) {
    this.val = val;
}
public int getVal() {
    return this.val;
}
}
public class TestDeom {
    public static void main(String[] args) {
      TestArray[] t1 = new TestArray[4];
      t1[0] = new TestArray();
      t1[1] = new TestArray();
      t1[2] = new TestArray();
      t1[3] = new TestArray();
      TestArray[] t2 = new TestArray[4];//t2[0]
      for (int i = 0; i < t1.length; i++) {
        t2[i] = t1[i];
    }
        for (int i = 0; i < t1.length; i++) {
        System.out.print(t1[i].getVal() + " ");
    }
        System.out.println();
        for (int i = 0; i < t2.length; i++) {
        System.out.print(t2[i].getVal() + " ");
    }
        System.out.println();
         t2[0].setVal(100000);
         System.out.println("===============");

        for (int i = 0; i < t1.length; i++) {
        System.out.print(t1[i].getVal() + " ");
    }
    System.out.println();
    for (int i = 0; i < t2.length; i++) {
        System.out.print(t2[i].getVal() + " ");
    }
}

}
在這裡插入圖片描述
由結果可以看出,當對複製陣列的某個元素進行改變時,被複制陣列對應元素也隨之改變,即對於引用資料型別來說for迴圈語句是淺拷貝。

2.System.arraycopy()方法:

通過原始碼可以看到,其為native方法,即原生態方法。自然效率更高。
 
public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);

如果是陣列比較大,那麼使用System.arraycopy會比較有優勢,因為其使用的是記憶體複製,省去了大量的陣列定址訪問等時間
 System.arraycopy()原始碼,可以看到是native方法:native關鍵字說明其修飾的方法是一個原生態方法,方法對應的實現不是在當前檔案,而是在用其他語言(如C和C++)實現的檔案中。 可以將native方法比作Java程式同C程式的介面。
 System.arraycopy是不安全的。

src:源陣列;
srcPos:源陣列要複製的起始位置;
dest:目的陣列;
destPos:目的陣列放置的起始位置;
length:拷貝元素的長度.
注意:src和dest必須是同類型或者可以進行轉換型別的陣列,否則會丟擲執行時異常ArrayStoreException.如果指定位置或長度計算得出的下標索引越界,則會丟擲異常 ArrayIndexOutOfBoundsException.

import  java.util.Arrays;
   public class ArrayCopysystem {
    public static void main(String[] args) {
    int[] array = {1,2,3,4,5,6,7,8,9};
    int[] brray = Arrays.copyOf(array,array.length);

    System.out.println(Arrays.toString(array));
    System.out.println(Arrays.toString(brray));
    brray[0] = 1000;
    System.out.println("=================");
    System.out.println(Arrays.toString(array));
    System.out.println(Arrays.toString(brray));
}
   }

在這裡插入圖片描述
System.arraycopy() 在拷貝陣列的時候,採用的使用潛複製,複製結果是一維的引用變數傳遞給副本的一維陣列,修改副本時,會影響原來的陣列。

 import  java.util.Arrays;
 public class ArrayCopysystem {
    public static void main(String[] args) {
    stArray[] t1 = new TestArray[4];
    t1[0] = new TestArray();
    t1[1] = new TestArray();
    t1[2] = new TestArray();
    t1[3] = new TestArray();
    TestArray[] t2 = Arrays.copyOf(t1,t1.length);

    for(int i = 0;i < t1.length;i++) {
        System.out.print(t1[i].getVal()+" ");
    }
    System.out.println();
    for(int i = 0;i < t2.length;i++) {
        System.out.print(t2[i].getVal()+" ");
    }
    System.out.println();
    t2[0].setVal(100000);
    System.out.println("===============");

    for(int i = 0;i < t1.length;i++) {
        System.out.print(t1[i].getVal()+" ");
    }
    System.out.println();
    for(int i = 0;i < t2.length;i++) {
        System.out.print(t2[i].getVal()+" ");
    }

} 

在這裡插入圖片描述

3.Arrays.copyOf()方法:

同樣看原始碼,它的實現還是基於System.arraycopy(),所以效率自然低於System.arraycpoy()。

      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;}

 例子:public class Arraycopy {
          public static void main(String[] args) {
          TestArray[] t1 = new TestArray[4];
          t1[0] = new TestArray();
          t1[1] = new TestArray();
          t1[2] = new TestArray();
          t1[3] = new TestArray();
          TestArray[] t2 = new TestArray[4];//t2[0]

          System.arraycopy(t1,0,t2,0,t1.length);

          for(int i = 0;i < t1.length;i++) {
          System.out.print(t1[i].getVal()+" ");
}
          System.out.println();
          for(int i = 0;i < t2.length;i++) {
          System.out.print(t2[i].getVal()+" ");
}
          System.out.println();
          t2[0].setVal(100000);
          System.out.println("===============");

          for(int i = 0;i < t1.length;i++) {
          System.out.print(t1[i].getVal()+" ");
}
          System.out.println();
          for(int i = 0;i < t2.length;i++) {
          System.out.print(t2[i].getVal()+" ");
}

 }}

在這裡插入圖片描述

public class Arraycopy {
public static void main(String[] args) {
    int[] array = {1,2,3,4,5,6,7,8,9};
    int[] brray = new int[array.length];
    System.arraycopy(array,0,brray,0,array
            .length);
    System.out.println(Arrays.toString(array));
    System.out.println(Arrays.toString(brray));
    brray[0] = 1000;
    System.out.println("=================");
    System.out.println(Arrays.toString(array));
    System.out.println(Arrays.toString(brray));

}
 }

在這裡插入圖片描述
(1)copyOf()的實現是用的是arrayCopy();
(2)arrayCopy()需要目標陣列,對兩個陣列的內容進行可能不完全的合併操作。
(3)copyOf()在內部新建一個數組,呼叫arrayCopy()將original內容複製到copy中去,並且長度為newLength。返回copy;

4. Object.clone()方法:

從原始碼來看同樣也是native方法,但返回為Object型別,所以賦值時將發生強轉,所以效率不如之前兩種。

    View code1 protected native Object clone()throwsCloneNotSupportedException;
    
    import  java.util.Arrays;
  public class Clone {
          public static void main(String[] args) {
          int[] array = {1, 2, 3, 4, 5, 6, 7, 8, 9};
          int[] brray = array.clone();

          System.out.println(Arrays.toString(array));
          System.out.println(Arrays.toString(brray));
          brray[0] = 1000;
          System.out.println("=================");
          System.out.println(Arrays.toString(array));
          System.out.println(Arrays.toString(brray));

}
  }

在這裡插入圖片描述
由結果可以看出,當對複製陣列的某個元素進行改變時,並不影響被複制陣列對應元素,即對於基本資料型別來說clone()方法實現陣列拷貝也屬於深拷貝。

    import  java.util.Arrays;
    public class Clone {
          public static void main(String[] args) {
          TestArray[] t1 = new TestArray[4];
          t1[0] = new TestArray();
          t1[1] = new TestArray();
          t1[2] = new TestArray();
          t1[3] = new TestArray();
          TestArray[] t2 = new TestArray[4];//t2[0]
          for (int i = 0; i < t1.length; i++) {
          t2[i] = t1[i];
    }
           for (int i = 0; i < t1.length; i++) {
           System.out.print(t1[i].getVal() + " ");
    }
           System.out.println();
           for (int i = 0; i < t2.length; i++) {
           System.out.print(t2[i].getVal() + " ");
    }
           System.out.println();
           t2[0].setVal(100000);
           System.out.println("===============");

           for (int i = 0; i < t1.length; i++) {
           System.out.print(t1[i].getVal() + " ");
    }
           System.out.println();
           for (int i = 0; i < t2.length; i++) {
           System.out.print(t2[i].getVal() + " ");
    }
}
 }

在這裡插入圖片描述
由結果可以看出,當對複製陣列的某個元素進行改變時,被複制陣列對應元素也隨之改變,即對於引用資料型別來說clone()方法是淺拷貝。

時間複雜度有:

  常數階O(1),  對數階O(log2n),  線性階O(n),  線性對數階O(nlog2n),  平方階O(n^2), 立方階O(n^3),..., k次方階O(n^k), 指數階O(2^n) 。
     
 (1)   for(i=1;i<=n;i++)   //迴圈了n*n次,當然是O(n^2)
 
        for(j=1;j<=n;j++)
        
             s++;
            
 (2)   for(i=1;i<=n;i++)//迴圈了(n+n-1+n-2+...+1)≈(n^2)/2,因為時間複雜度是不考慮係數的,所以也是O(n^2)
        for(j=i;j<=n;j++)
        
             s++;
             
 (3)   for(i=1;i<=n;i++)//迴圈了(1+2+3+...+n)≈(n^2)/2,當然也是O(n^2)
        for(j=1;j<=i;j++)
             s++;
             
 (4)   i=1;k=0;      while(i<=n-1){           k+=10*i;      i++;      }//迴圈了n-1≈n次,所以是O(n)
 
 (5)   for(i=1;i<=n;i++)  
         
    for(j=1;j<=i;j++)        
        
      for(k=1;k<=j;k++)    
                     
     x=x+1;
 //迴圈了(1^2+2^2+3^2+...+n^2)=n(n+1)(2n+1)/6≈(n^3)/3,不考慮係數,自然是O(n^3)另外,在時間複雜度中,log(2,n)(以2為底)與lg(n)(以10為底)是等價的,因為對數換底公式:log(a,b)=log(c,b)/log(c,a)所以,log(2,n)=log(2,10)*lg(n),忽略掉係數,二者當然是等價的。

練習

將奇數放在偶數前面

import  java.util.Arrays;
public class Part {

    public static void main(String[] args) {
    
    int[] a = {8,4,1,6,7,4,9,6,4};
    
  sort(a);
    
    System.out.println(a);
    
    System.out.println(Arrays.toString(a));    }        // 排序實現
    
    public  static void sort(int[] a) {
    
    for (int i = 0; i < a.length - 1; i++) {      
       
    if (a[i] % 2 == 0) {//能被2整除的數都是偶數,反之為奇數
    
    int j= i + 1;
    
    while (i< a.length) {
    
     if (a[j] % 2 != 0) {
    
     int temp = a[i];
     
      a[i] = a[j];
      
      a[j] = temp;
      
      break;
    }
      j++;
           }            //說明後面的全部均為偶數,沒必須要往下迴圈。
      if (j == a.length) {
      
               break;
           }
       }
    }
}}

在這裡插入圖片描述

一個數組是有序的,給定一個key:數字 有兩個數字的和加起來等於key 找到這兩個數字的下標

  import java.util.Scanner;
  public class Key {
        public static void main(String[] args) {
        int[] a = {1, 2, 3, 4, 5, 6, 7, 8, 9};
        Scanner scanner = new Scanner(System.in);
        int key = scanner.nextInt();   //輸入key的值
        int i = 0;
        int j;
        int temp = 0;
        for (; i < a.length - 1; i++) {          //遍歷一遍陣列
        temp = key - a[i];        //確定要尋找的數的值
        for (j = i + 1; j < a.length; j++) {     //開始查詢temp
        if (temp == a[j]) {           //如果找到,就輸出出來
        System.out.println(key + "等於第" + (i + 1) + "個與第" + (j + 1) + "個數的和");
                }
            }
        }
    }
}

在這裡插入圖片描述
一個整形陣列,除了兩個數字只出現一次外
其他數字都是兩次。{1,3,1,2,3,4} 找到這兩個數字

import java.util.Arrays;
import java.util.Scanner;
public class Subscript {
    public static void main(String[] args)
{
    int[] a={2,4,3,6,3,2,5,5};
    
    int[] a1={0};
    
    int[] a2={0};
    
    FindNumsAppearOnce(a,a1,a2);
}

public static void FindNumsAppearOnce(int [] array,int num1[] , int num2[])
{

    if(array==null||array.length==0)
    
        return;
        
    int number=0;
    
    for(int i:array)
    {
    
        number^=i;
    }
    
    int index=getBit1(number);
    
    int number1=0;
    
    int number2=0;
    
    for(int i:array)
            {
        if(get1(i,index))
        
            number1^=i;
        else
        
            number2^=i;
    }
    
    num1[0]=number1;
    
    num2[0]=number2;
    
    System.out.print(num1[0]);
    
    System.out.print("   ");
    
    System.out.println(num2[0]);
}


private static boolean get1(int i, int key)
{
    i=  i>>key;

    return (i&1)==0;
}
private static int getBit1(int number)
{
    int key=0;
    
    while((number&1)==0)
    {
        number=number>>1;
        
        key++;
    }
    return key;
}
 }

在這裡插入圖片描述

熟悉Arrays這個類裡面的方法

Arrays.equals(): 比較兩個陣列是否相同,返回布林;

Arrays.deepEqual(): 進行深度(多維陣列)比較;
Arrays.binerySearch(): 查元素在陣列中的位置;
可以使用二分搜尋法來搜尋指定的陣列,以獲得指定物件,該方法返回要搜尋元素的索引值。
binerySearch()方法提供多種過載形式,用於滿足各種型別的查詢需要。
Arrays.copyOf(): 複製一個數組,就是進行擴容,它可以直接傳回一個新的陣列物件。
跟他相似的有Arrays.copyOfRange()和SystemasList();
Arrays.toString(): 返回一個受指定陣列內容的字串表達形式,和他相似的有Arrays.deepToString();
Arrays.fill(): 用於填充陣列,

fill(a,val)
a是陣列變數,給陣列中的每個值都賦為val

Arrays.Sort(): 將陣列排好序。
根據傳出引數的長度的大小來判斷用哪種排序方法。
如何排序陣列並插入某個元素?

 import java.util.Arrays;

 public class Interpposition {
 
      public static void maopao(int[] array){
      
      int tmp;//定義一個臨時量
      for (int i = 0; i<array.length; i++) {{//外層迴圈控制排序趟數
  
      for (int j = 0; j <array.length-1-i; j++)
       {//內層迴圈控制每一趟排序多少次

          if(array[j]>array[j+1])
          {
          
              tmp = array[j];
              
              array[j] = array[j+1];
              
              array[j+1] = tmp;
              //比較兩個相鄰的元素,將值大的元素交換至右端。
          }
      }
  }
 }

  public static void main(String[] args) {
  
      int[] array = {1,76,28,24,3,6,4,9};
      
      int cha = 22;//插入的數
      
      int[] array1 = new int[array.length+1];
      
      array1[0]  = cha;//將要插入的數放在陣列的第一位
      
      System.out.println("原陣列為:");
      
      for (int i = 0; i < array.length; i++) {
      
          System.out.print(array[i]+"  ");
      }//輸出原陣列
      
      System.out.println();
      
      for (int i = 0; i< array.length; i++) {
      
          array1[i+1] = array[i];//插入數字後,將原陣列的數統一後移一位
      }
      maopao(array1);//使用冒泡法給array1排序
      
      System.out.println("插入後的排序為:");
      
      for (int i = 0; i < array1.length; i++) {
      
          System.out.print(array1[i]+"  ");
      }
      System.out.println();//輸出排序後的新陣列
  }
  }

在這裡插入圖片描述

如何搜尋陣列中的最小值和最大元素?

import java.util.Arrays;
import java.util.Collections;
public class Big {

    public static void main(String[] args) {
    
        int numbers[] = new int[] { 28, 21, 11, 41, 34,69, 15 };
        
        int s = numbers[0];//把第一個數賦值給s;
        
        int l = numbers[0];//把第一個數賦值給l;

        for (int i = 1; i < numbers.length; i++) {
        
        if (numbers[i] > l)//如果這個數大於當前的最大數
        
        l = numbers[i];//此時這個數為最大數    
              
          else if (numbers[i] < s)//如果這個數小於最小數
          
        s = numbers[i];//此時這個數為最小數   
        }
        
        System.out.println("Largest Number is : " + l);//輸出最大數
        
        System.out.println("Smallest Number is : " + s)//輸出最小數
    }
}

在這裡插入圖片描述
如何合併兩個陣列(合併到一個新的陣列)?

    import java.util.Arrays;

    public class Combine {
    
        public static void main(String[] args) {
        //定義兩個陣列並初始化
        int[] a = {1,2,3,4,5};
        
        int[] b = {6,7,8,9,10};
        
        int[] c = new int[a.length+b.length];//引入一個新的陣列
        
        System.arraycopy(a, 0, c, 0, a.length);
        //使用Arrays.copyOf()方法將陣列a中的值複製到陣列c中
        
        System.arraycopy(b, 0, c, a.length, b.length);
         //使用Arrays.copyOf()方法將陣列b中的值複製到陣列c中
         
        System.out.println(Arrays.toString(c));//輸出陣列c
    }
  }  
 }

在這裡插入圖片描述

如何刪除陣列指定元素?

import  java.util.Arrays;

import java.util.Scanner;

public class Delet {

public static void main(String[] args) {

//把最後一個元素替代指定的元素,然後陣列縮容

    Scanner sc = new Scanner(System.in);//建立一個新物件
    
    int[] arr = new int[]{1, 2, 4, 5, 9, 8, 0};
    
    System.out.println(Arrays.toString(arr));
    
    System.out.println("請輸入要刪除第幾個元素:");
    
    int n = sc.nextInt();
    
    sc.close();
  //把最後一個元素替代指定的元素
    arr[n - 1] = arr[arr.length - 1];
  //陣列縮容
  
    arr = Arrays.copyOf(arr, arr.length - 1);//把縮容後的陣列複製
    
    System.out.println(Arrays.toString(arr));
}
 }

在這裡插入圖片描述
如何填充陣列(一次填充,部分填充)?

 import  java.util.Arrays;
 
 import com.sun.deploy.util.ArrayUtil;
 
 public class Sortxu {
 
            public static void main(String[]   agrs){
            
            int array[] = new int[6];//建立新物件
            
            Arrays.fill(array, 100);//一次填充數字100
            
            for (int i=0, n=array.length; i < n; i++) {
            
                System.out.print(array[i] + ",");//輸出填充了的陣列
                
            }
            System.out.println();
            
            Arrays.fill(array, 3, 6, 50);//部分填充
            
            for (int i=0, n=array.length; i< n; i++) {
            
            System.out.print(array[i] + ",");//輸出
            }
        }
    }

在這裡插入圖片描述
** 如何從陣列中查詢常見的元素? **

import  java.util.Scanner;

public class Find {

public static void main(String[] args) {
//定義並初始化陣列

int[] arr = {22,33,44,55,66,7,2,5,24};
//定義並初始化Scanner物件,用於獲取輸入鍵盤輸入的內容

Scanner scanner = new Scanner(System.in);
//輸出資訊

System.out.print("請輸入需要查詢的數字:");
//獲取鍵盤輸入要查詢的數字

int target = scanner.nextInt();
//迴圈陣列

for(int i  = 0; i < arr.length; i++) {
    //如果輸入的數字跟當前陣列的元素的值相同
    
    if(target == arr[i]) {
        //輸入所在位置,從1開始
        
        System.out.println(target + "位於數字的第" + (i + 1) + "位");
        //結束
        return;
    }
}
//如果找不到的話就提示一下
System.out.println("陣列中不存在數字:" + target);
  }
}

在這裡插入圖片描述
在這裡插入圖片描述