数组拷贝方法

数组拷贝的方法有四种

分别为: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);
  }
}

在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43301647/article/details/83153081