Java基础——Arrays类

每日正能量

如果你要做一件事,不要到处宣言自己的想法,只管安安静静地去做,值不值,时间是最好的证明,自己的人生,得自己负责。

Arrays类

 

JDK中提供了一个专门用于操作数组的工具类,即Arrays类,位于java util 中。

用前需导包:import java.util.Arrays;

1. Arrays类常用方法

返回类型 方法 说明
String toString(array) 将数组array转换成字符串
void sort(array) 对数组进行升序排列。注意:排序算法是由Vladimir Yaroslavskiy,Jon Bentley和Joshua Bloch提供的双轴快速排序。
void fill(arr,val) 将数组arr全部元素赋值为val
boolean equals(arr1,arr2) 判断两个数组是否相等
与arr类型相同 copyOf(arr,length) 将数组arr复制成一个长度为length的新数组
int binarySearch(arr, val) 查询元素val在arr中的下标值

示例代码:

public class Test {
    public static void main(String[] args) {
        int a[]={12,20,13,42,72,26,35,10,46,26,53};
        int b[]={3,5,7,8,54,23,9};
        int c[]={3,5,7,8,54,23,9};
 
        String str=Arrays.toString(a);       //将特定数组转换成字符串
        System.out.println("字符串:"+str);
        
        Arrays.sort(a);                      //对数组array的元素进行升序排列
        System.out.println("排序后:"+Arrays.toString(a)); 
        
        Arrays.fill(a,10);                   //所以元素都赋值成特定值
        System.out.println("赋值后:"+Arrays.toString(a)); 
        
        boolean boo=Arrays.equals(a,b);      //判断两个数组是否相等(对应位置上的元素是否相等)
        boolean boo2=Arrays.equals(b, c);
        System.out.println("a:"+a);
        System.out.println("b:"+b);
        System.out.println("c:"+c);
        System.out.println("ab相等?"+boo);
        System.out.println("bc相等?"+boo2);
        
 
        int d[]=Arrays.copyOf(b,b.length);   //把数组复制成特定长度的数组,与直接赋值(引用传递)不同
        System.out.println("d:"+Arrays.toString(d));
        System.out.println("d:"+d);
        System.out.println("b:"+b);
        
        int i=Arrays.binarySearch(b, 5);     //查询特定因素在数组中的下标
        System.out.println("下标是:"+i);
    }
}

运行结果:

Java基础——Arrays类_第1张图片 

2. for在数组中的特殊用法

for(元素类型 变量名:要循环的数组或集合名){
 
       //循环对每个元素进行操作
 
}

第一个元素类型是数组中元素的类型,变量名在循环时原来保存每个元素的值,冒号后面是要循环的数组名称。

3. Arrays源码解析

public static String toString(int[] a)  将数组array转换成字符串

int[] arr = { 24, 69, 80, 57, 13 };
System.out.println("排序前:" + Arrays.toString(arr));

public static String toString(int[] a) {
	//a -- arr -- { 24, 69, 80, 57, 13 }

    if (a == null)
        return "null"; //说明数组对象不存在
    int iMax = a.length - 1; //iMax=4;
    if (iMax == -1)
        return "[]"; //说明数组存在,但是没有元素。

    StringBuilder b = new StringBuilder();
    b.append('['); //"["
    for (int i = 0; ; i++) {
        b.append(a[i]); //"[24, 69, 80, 57, 13"
        if (i == iMax)
        	//"[24, 69, 80, 57, 13]"
            return b.append(']').toString();
        b.append(", "); //"[24, 69, 80, 57, "
    }
}

public static int binarySearch(int[] a,int key)  二分查找        

int[] arr = {13, 24, 57, 69, 80};
System.out.println("binarySearch:" + Arrays.binarySearch(arr, 577));
​
public static int binarySearch(int[] a, int key) {
    //a -- arr -- {13, 24, 57, 69, 80}
    //key -- 577
    return binarySearch0(a, 0, a.length, key);
}
​
private static int binarySearch0(int[] a, int fromIndex, int toIndex,
                                 int key) {
    //a -- arr --  {13, 24, 57, 69, 80}
    //fromIndex -- 0
    //toIndex -- 5
    //key -- 577                           
                                 
                                 
    int low = fromIndex; //low=0
    int high = toIndex - 1; //high=4
​
    while (low <= high) {
        int mid = (low + high) >>> 1; //mid=2,mid=3,mid=4
        int midVal = a[mid]; //midVal=57,midVal=69,midVal=80
​
        if (midVal < key)
            low = mid + 1; //low=3,low=4,low=5
        else if (midVal > key)
            high = mid - 1;
        else
            return mid; // key found
    }
    return -(low + 1);  // key not found.
}

public static int[] copyOf(int[] original, int newLength)

public static  T[] copyOf(U[] original, int newLength, Class newType) {
    @SuppressWarnings("unchecked")
    T[] copy = ((Object)newType == (Object)Object[].class)
        ? (T[]) new Object[newLength]
        : (T[]) Array.newInstance(newType.getComponentType(), newLength);
    System.arraycopy(original, 0, copy, 0,
                     Math.min(original.length, newLength));
    return copy;
}

可以看到,最终调用的是System.arraycopy()方法.

/**
*System.arraycopy();
*/
public static native void arraycopy(Object src,  int srcPos, Object dest, int destPos, int length);

可以看到,它是一个静态本地方法,由虚拟机实现,效率自然比用java一个个复制高.

方法含义

从源数组src取元素,范围为下标srcPos到srcPos+length-1,取出共length个元素,存放到目标数组中,存放位置为下标destPos到destPos+length-1。

简单说,就是数组间的复制。

应用

常用作数组的扩容,如ArrayList底层数组的扩容。

参数

  1. Object src:the source array. 源数组

  2. int srcPos:starting position in the source array. 在源数组中,开始复制的位置

  3. Object dest:the destination array. 目标数组

  4. int destPos:starting position in the destination data. 在目标数组中,开始赋值的位置

  5. int length:the number of array elements to be copied. 被复制的数组元素的数量

过程详解

以下面这个例子进行分析

public class SystemArrayCopy {
 public static void main(String[] args) {
    int[] src = {1, 2, 3, 4};
    int[] dest = new int[5];
    System.arraycopy(src, 0, dest, 1, 4);
​
    for (Object o : dest) {
        System.out.println(o);
    }
}
}
/*
0 1 2 3 4
*/
src = |1|2|3|4|
dest = |0|0|0|0|0|
执行System.arraycopy(src, 0, dest, 1, 4);时
第一步:从源数组(src)中,从下标0开始取,取4个,也就是src[0]-src[3],即1 2 3 4四个数
第二步:把取出的数,按顺序,存放到目标数组(dest)中,从下标1开始存,存4个,也就是dest[1]-dest[4]
所以数组dest为:|0|1|2|3|4|

注意,目标数组下标范围外的元素不会改变!

4. 深复制与浅复制

当数组为一维数组,且元素为基本类型或String类型时,属于深复制,即原数组与新数组的元素不会相互影响 当数组为多维数组,或一维数组中的元素为引用类型时,属于浅复制,原数组与新数组的元素引用指向同一个对象 这里说的影响,是两个数组复制后对应的元素. String的特殊是因为它的不可变性

  1. 一维数组,元素为基本类型

    public class SystemArrayCopy {
    ​
     public static void main(String[] args) {
         String str1 = "aa";
         String str2 = "bb";
         String str3 = "cc";
         String str4 = "dd"; 
         String[] src = {str1, str2, str3, str4};
         String[] dest = new String[4];
    ​
         System.arraycopy(src, 0, dest, 0, 4);
    ​
         System.out.println("改变前");
         print("src = ", src);
         print("dest = ", dest);
    ​
         src[0] = "abcd";
    ​
         System.out.println("改变后");
         print("src = ", src);
         print("dest = ", dest);
       }
    ​
        private static void print(String string, String[] arr) {
            System.out.print(string);
            for (String str : arr) {
                System.out.print(str + " ");
            }
            System.out.println();
        }
    ​
    }
    /*
    改变前
    src = aa bb cc dd 
    dest = aa bb cc dd 
    改变后
    src = abcd bb cc dd 
    dest = aa bb cc dd 
    */
    ​

    可以看到,源数组第0个元素改变,并不会影响到目标数组

  2. 多维数组

    public class SystemArrayCopy {
    ​
     public static void main(String[] args) {
         int[] arr1 = {1, 2};
         int[] arr2 = {3, 4};
         int[] arr3 = {5, 6};
         int[] arr4 = {7, 8};
         int[][] src = new int[][]{arr1, arr2, arr3, arr4};
         int[][] dest = new int[4][];
    ​
         System.arraycopy(src, 0, dest, 0, 4);
    ​
         System.out.println("改变前");
         print("src = ", src);
         print("dest = ", dest);
    ​
         src[0][0] = 11111;
    ​
         System.out.println("改变后");
         print("src = ", src);
         print("dest = ", dest);
          }
    ​
     // 简单输出二维int数组的方法
     private static void print(String string, int[][] arr) {
         System.out.print(string);
         for (int[] a : arr) {
             for (int i : a) {
                 System.out.print(i + " ");
             }
             System.out.print(",");
         }
         System.out.println();
     }
    }
    /*
    改变前
    src = 1 2 ,3 4 ,5 6 ,7 8 ,
    dest = 1 2 ,3 4 ,5 6 ,7 8 ,
    改变后
    src = 11111 2 ,3 4 ,5 6 ,7 8 ,
    dest = 11111 2 ,3 4 ,5 6 ,7 8 ,
    */

源数组改变后,目标数组也跟改变了,这就是浅复制

5. 数组拷贝的4种方法

1、for

使用for循环自己实现数组的复制

2、clone

克隆方法我们在数组中是找不到的,它是object的方法,我们先看看源码

protected native Object clone() throws CloneNotSupportedException;

看到了修饰符native,说明是由c或者c++实现的,它的优点是速度快,它返回了object对象,所以使用的时候需要用对象接收返回值。

3、System.arraycopy()

通过上述源码我们看到也是native修饰的,所以底层也是用c或者c++实现的,但是可以看到没有返回值,clone()还需要对返回值进行类型转换,所以它的速度是要比clone()要快的,这也是牛客网的一道题,问的就是四种拷贝哪种是最快的,答案肯定是System.arraycopy()。

4、Arrays.copyof();

在方法内部调用了System.arraycopy(),相当于换了名字。

你可能感兴趣的:(java,算法,排序算法)