Java数组的定义与使用(二)

我们来继续上一篇博客中对Java中数组的解读,
我们先来回顾一下
Java数组的定义与使用(二)_第1张图片
感兴趣的小伙伴可以进去看看哦数组(一)
数组(一)中我们解读到了数组的应用场景
那么这篇博客主要针对数组的一些练习和运用以及二维数组进行解析

Java数组的定义与使用(二)_第2张图片

数组练习

数组转化为字符串

Java数组的定义与使用(二)_第3张图片
使用这个我们以后打印数组就会更加方便一点。
Java中提供了java.util.Arrays包,其中包含了一些操作数组的常用方法。
这里给大家列举几个常用的方法
1、二叉搜索算法
Java数组的定义与使用(二)_第4张图片
使用二叉搜索算法搜索指定值的指定数组的范围。在进行此呼叫之前,范围必须按照sort(int[], int, int)方法进行排序。如果没有排序,结果是未定义的。如果范围包含具有指定值的多个元素,则不能保证将找到哪个元素。
2、复制数组内容(下面我还会再提到)
Java数组的定义与使用(二)_第5张图片
复制指定的数组,用零截取或填充(如有必要),以便复制具有指定的长度。对于原始数组和副本都有效的所有索引,两个数组将包含相同的值。对于在副本中而不是原件有效的任何索引,副本将包含0 。当且仅当指定长度大于原始数组的长度时,这些索引才会存在。
3、数组深度比较
Java数组的定义与使用(二)_第6张图片

  • 返回指定数组的内容的字符串表示形式。 如果数组包含其它数组作为元件,它们被转换为字符串Object.toString()从Object继承的方法,其描述了他们的身份 ,而不是其内容。
  • 返回指定数组的“深度内容”的字符串表示形式。
//如果数组包含其他数组作为元素,则字符串表示包含其内容等等。
//此方法用于将多维数组转换为字符串。
//字符串表示由数组元素的列表组成,括在方括号( "[]" )中。 
//相邻的元素由字符", " (逗号后跟一个空格)分隔开。 
//元件由String.valueOf(Object)转换为字符串,除非它们本身阵列。 
//如果一个元素e是一个基本类型的阵列,它通过调用的Arrays.toString(e)适当重载转换为字符串作为。 
//如果元素e是引用类型的数组,则通过递归调用此方法将其转换为字符串。 
//为了避免无限递归,如果指定的数组包含自身作为元素,或者通过一个或多个数组级别包含对其自身的间接引用,则将自引用转换为字符串"[...]" 。
//例如,仅包含对其自身的引用的数组将被呈现为"[[...]]" 。
 //如果指定数组是null此方法返回"null"。 

4、️按照数组顺序排序
Java数组的定义与使用(二)_第7张图片
按照数字顺序排列数组的指定范围。要排序的范围从索引fromIndex (包括)扩展到索引toIndex 。如果fromIndex == toIndex ,要排序的范围是空的。
a - 要排序的数组
fromIndex - 要排序的第一个元素的索引(包括)
toIndex - 最后一个要排序的元素的索引
4、equals比较和fill填充
这里用代码来解释

  public static void main_ArrayEqualsAndFill(String[] args) {
        int[] array1 = {1,2,3,4,5};
        int[] array2 = {1,2,3,4,5};
        boolean equal = Arrays.equals(array1,array2);
        System.out.println(equal);
        System.out.println("==============");
        int[] array = new int[10];
        System.out.println("填充之前的数组"+Arrays.toString(array));
//        结果都是0
        Arrays.fill(array,1);
        System.out.println("填充之后的数组"+Arrays.toString(array));
//        结果都是1
        Arrays.fill(array,4,10,29);
//        从[4,10)填充29

    }

其他的我就不多做介绍了,小伙伴们可以自己去了解一下~
这里我们其实就可以发现了,重载函数真的很常见!

数组的拷贝

这里我们用代码来进行讲解
Java数组的定义与使用(二)_第8张图片
运行结果
Java数组的定义与使用(二)_第9张图片
这里newArr和arr引用的是同一个数组,因此newArr修改空间中内容之后,arr也可以看到修改的结果

Java数组的定义与使用(二)_第10张图片
运行结果
image.png
使用Arrays中copyOf方法完成对数组的拷贝:
copyOf方法在进行数组拷贝时,创建了一个新的数组
arr和newArr引用的不是同一个数组
因为arr修改其引用数组中内容时,对newArr没有任何影响
image.png
运行结果
newArr2:[3,4]
这里有一点要注意的是,从2下标拷贝到4下标,都是左闭右开的,不要搞错[2,4)
这个copyOfRange方法看起来很方便呀!让我们瞧瞧得用CTRL+左键来管中窥豹一下源码吧
Java数组的定义与使用(二)_第11张图片
啊,就这么短短几行!而且一眼看过去就可以清楚每行代码的用途,简单干练。
果然还是那句话,最好的代码不是生涩难懂的,而是大家都能看得明白的!
这里我简单画个图来帮大家理解一下
Java数组的定义与使用(二)_第12张图片
Java数组的定义与使用(二)_第13张图片
我们在这里要注意的是:数组当中存储的是基本类型数据的时候,不论怎么拷贝基本都不会出现什么问题,但如果存储的是引用数据类型,拷贝的时候就需要考虑深浅拷贝的问题,Arrays中也有相关deepCopyOf等方法,这里待我将数据结构学习透彻再为大家讲解

除了用Java提供的方法,我们当然也可以运用自己写的拷贝数组的方法
Java数组的定义与使用(二)_第14张图片
运行结果
Java数组的定义与使用(二)_第15张图片

求数组中元素的平均值

Java数组的定义与使用(二)_第16张图片

//    求平均值
public static double avg(int[] array) {
    int sum = 0;
    for (int i = 0;i<array.length;i++){
        sum = sum +array[i];
    }
    return sum*1.0/array.length;
    //        不能 return sum/array.length
    }

查找数组中指定元素(顺序查找)

Java数组的定义与使用(二)_第17张图片

    public static int search(int[] array,int key){
        for(int i=0;i<array.length;i++){
            if(array[i]==key){
                return i;
            }
        }
//        如果代码走到这里,说明推出了for循环
        return  -1;//因为数组没有负数下标
    }
    public static void main_search(String[] args) {
        int[] array = {1,2,3,4,5};
        int index = search(array,4);
        if(index == -1){
            System.out.println("没有你要找的关键字!");
        }else {
            System.out.println("找到了你要的关键字,下标是:"+ index);
        }
    }

查找数组中指定元素(二分查找)

针对有序数组我们可以进行更加快速的二分查找,一定要注意,是有序!也就是说二分查找的前提是数组是排好序的,千万不要因为这个小细节犯错哦。
而有序数组分为升序降序,1234为升序,4321为降序
Java数组的定义与使用(二)_第18张图片

以升序数组为例,二分查找的思路是先取中间位置的元素,然后使用待查找元素与数组中间元素进行比较:

  • 如果相等的话,即找到了返回元素在数组中的下标
  • 如果小于,以类似方法到数组左半侧进行查找
  • 如果大于,以类似方法到数组右半侧进行查找
//    二分查找,前提是查找的数组有序
    public static int binarySearch(int[] array,int key){
        int left = 0;
        int right = array.length-1;
        while (left<=right){
            int mid = (left + right) /2;
            if (array[mid]<key){
                left = mid + 1;
            }else if(array[mid]==key){
                return mid;
            }else {
                right = mid -1;
            }
        }
//        代码走到这里说明left已经大于right了,所以返回-1
        return -1;//数组没有-1
    }

可以看到,针对一个很多元素的数组查找,二分查找的效率极其高,随着数组元素个数越多,那么二分的优势就越大

Arrays中的sort排序方法

Java数组的定义与使用(二)_第19张图片
(字好丑小伙伴们谅解一下~)
我们用代码来演示一下
Java数组的定义与使用(二)_第20张图片
这里的sort会自动为我们排序,但它是默认升序的,那么我们再来见识一下源码
Java数组的定义与使用(二)_第21张图片
!这又是一个方法,哼哼我再点进去看看
Java数组的定义与使用(二)_第22张图片

…好家伙,4162行代码,见识不过来了,等有空我再为大家去庖丁解牛(鸽王发言)

数组排序(冒泡排序)

Java数组的定义与使用(二)_第23张图片
Java数组的定义与使用(二)_第24张图片
假设我们需要对数组进行升序排序

  1. 将数组中相邻元素从前往后依次进行比较,如果前一个元素比后一个元素大,则交换,一趟下来之后最大的元素就在数组的末尾
  2. 依次从上述过程,知道数组中所有的元素都排列好
public static void bubbleSort(int[] array) {
        //[0----len-1)i代表趟数
        for (int i = 0;i<array.length-1;i++){
            boolean flg = false;
            //j<4在这里可以不减i    减i说明是进行了优化
            for(int j=0;j<array.length-1-i;j++){
                if (array[j] > array[j+1]) {
                    int tmp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = tmp;
                    flg = true;
                }
            }
            if (flg == false) {
//                这里是判断上一次有没有进行交换,flg有没有变成true
                break;
            }
        }
//        这里还可以进一步优化,我们可以进一步添加检查,
//        检查是否发生了简化,如果没有,说明有序了,就不需要进行第三趟,第四趟...
    }

Java数组的定义与使用(二)_第25张图片
冒泡排序相对Arrays提供的sort性能还是欠佳,所以还是多多利用Arrays提供的方法咯

数组逆序

我们给定一个数组,然后将里面的元素逆序排列

思路如下:
设定两个下标,分别指向第一个和最后一个元素,减缓两个位置的元素
然后让前一个下标自增,后一个下标自减,循环继续即可

    public static void reverse(int[] arr) {
        int left = 0;
        int right = arr.length-1;
        int tmp = 0;
        while (left<right){
            tmp = arr[left];
            arr[right] = tmp;
            left++;
            right--;
        }

很简单,就不细说啦

二维数组

基本语法

数据类型[][] 数组名称 = new 数据类型 [行数][列数] {初始化数据};

介绍几种初始化方式

import java.util.ArrayList;

public class TestDemo{
public static void main(String args[]) {
	int[][]a1= {{1,2},{3,4},{5,6,7}};
	for(int i=0;i<a1.length;i++) {
		System.out.print(a1[i].length+" ");
		for(int j=0;j<a1[i].length;j++)
			System.out.print(a1[i][j]+" ");
		System.out.println();
	}
	
	System.out.println();
	int[][]a2=new int[2][3];
	for(int i=0;i<a2.length;i++) {
		System.out.print(a2[i].length+" ");
		for(int j=0;j<a2[i].length;j++)
			System.out.print(a2[i][j]+" ");
		System.out.println();
	}
	
	System.out.println();
	int[][]a3=new int[2][];
	for(int i=0;i<a3.length;i++) {
		a3[i]=new int[3];
		System.out.print(a3[i].length+" ");
		for(int j=0;j<a3[i].length;j++)
			System.out.print(a3[i][j]+" ");
		System.out.println();
	}
	
	System.out.println();
	ArrayList<Integer> a4[]=new ArrayList[3];
	for(int i=0;i<a4.length;i++) {
		a4[i]=new ArrayList();
		a4[i].add(1);
		for(int j:a4[i])
			System.out.print(j+" ");
		System.out.println();
	}
}
}

输出

2 1 2 
2 3 4 
3 5 6 7 

3 0 0 0 
3 0 0 0 

3 0 0 0 
3 0 0 0 

1 
1 
1 

二维数组的用法和一维数组并没有明显的差别,所以不在赘述,除了要注意的是不规则数组的情况,
Java数组的定义与使用(二)_第26张图片
这里我给出一段代码,来帮助大家理解

 public static void main_3(String[] args) {
        int[] arr = {1,2,3,4,5,6};
        String newArr = Arrays.toString(arr);
        System.out.println(newArr);
    }

    public static void main_2(String[] args) {
//        int[][] array = {{1,2},{4,5,6}};是可以这样定义的
        int[][] array2=new int[2][];//这里编译器只知道这里有两行,还没给出列
        array2[0] = new int[2];
        array2[1] = new int[4];
//        这叫不规则数组
        for (int i = 0;i<array2.length;i++){//代表我们的行
            for (int j =0;j<array2[i].length;j++){//代表我们的列
                System.out.println(array2[i][j]);
            }
        }
//        这里没有array2[0] = new int[2];
//               array2[1] = new int[4];
//               会显示空指针异常,
//        PS:这里区别于C语言,不能再使用array+1来表示数组地址了
    }

    public static void main_1(String[] args){
//      二维数组不能这么写  int[][] array = {1,2,3,4,5,6};
        int[][] array = {{1,2,3},{4,5,6}};
        int[][] array2 = new int [][]{{1,2,3},{4,5,6}};

        for (int i = 0;i<2;i++){//代表我们的行
            for (int j =0;j<3;j++){//代表我们的列
                System.out.println(array[i][j]);
            }
        }
//        优化一下
        for (int i = 0;i<array.length;i++){//代表我们的行
            for (int j =0;j<array[i].length;j++){//代表我们的列
                System.out.println(array[i][j]);
            }
        }
        System.out.println("使用for-each来进行打印");
        for (int[] tmp:array){
            for(int x:tmp){
                System.out.println(x+" ");
            }
        }

        System.out.println("使用toString进行打印");
        System.out.println(Arrays.deepToString(array));
//
    }

以下是我在学习数组中用到的代码,如果有需要的小伙伴自取~

import java.util.Arrays;
public class TestDemo {


    public static void main(String[] args){
        int[] arr = {1,2,3,10,5,6};
        System.out.println(find(arr,10));
    }
    public static int find(int[] arr, int data){
        for (int i=0;i<arr.length;i++){
            if (arr[i] == data){
                return i;
            }
        }
        return -1;//
    }


    public static void main_average(String[] args) {
        int[] arr = {1,2,3,4,5,6};
        System.out.println(average(arr));
    }
    public static double average(int[] arr) {
        int sum = 0;
        for (int x: arr){
            sum += x;
        }
        return (double) sum/(double) arr.length;
    }//执行结果为3.5



    public static void main_4(String[] args) {
        int[] array = {1,2,3,4,5,6};
        int[] array2= new int[6];
        System.out.println("未拷贝前:" + Arrays.toString(array2));
        array2 = copyOf(array);
        System.out.println("拷贝了之后:"+Arrays.toString(array2));
    }
    public static int[] copyOf(int[] arr){
        int[] ret =new int[arr.length];
        for (int i = 0;i<arr.length;i++){
            ret[i] = arr[i];
        }
        return ret;
    }



    public static void copyOf2(int[] arr){

        //这里newArr和arr引用的是同一个数组
        //因此newArr修改空间中内容之后,arr也可以看到修改的结果
        int[] arr2 = {1,2,3,4,5,6};
        int[] newArr = arr2;
        newArr[0] = 10;
        System.out.println("newArr: "+Arrays.toString(arr2));

        arr[0] = 1;
        newArr = Arrays.copyOf(arr,arr.length);
        System.out.println("newArr:" + Arrays.toString(newArr));


//          使用Arrays中copyOf方法完成对数组的拷贝:
        //copyOf方法在进行数组拷贝时,创建了一个新的数组
        //arr和newArr引用的不是同一个数组
        //因为arr修改其引用数组中内容时,对newArr没有任何影响
        arr[0] = 10;
        System.out.println("arr:" + Arrays.toString(arr));
        System.out.println("newArr: "+Arrays.toString(newArr));

        //拷贝某个范围
        int[] newArr2 = Arrays.copyOfRange(arr,2,4);
        System.out.println("newArr2: "+ Arrays.toString(newArr2));
    }


    public static void main_3(String[] args) {
        int[] arr = {1,2,3,4,5,6};
        String newArr = Arrays.toString(arr);
        System.out.println(newArr);
    }

    public static void main_2(String[] args) {
//        int[][] array = {{1,2},{4,5,6}};是可以这样定义的
        int[][] array2=new int[2][];//这里编译器只知道这里有两行,还没给出列
        array2[0] = new int[2];
        array2[1] = new int[4];
//        这叫不规则数组
        for (int i = 0;i<array2.length;i++){//代表我们的行
            for (int j =0;j<array2[i].length;j++){//代表我们的列
                System.out.println(array2[i][j]);
            }
        }
//        这里没有array2[0] = new int[2];
//               array2[1] = new int[4];
//               会显示空指针异常,
//        PS:这里区别于C语言,不能再使用array+1来表示数组地址了
    }

    public static void main_1(String[] args){
//      二维数组不能这么写  int[][] array = {1,2,3,4,5,6};
        int[][] array = {{1,2,3},{4,5,6}};
        int[][] array2 = new int [][]{{1,2,3},{4,5,6}};

        for (int i = 0;i<2;i++){//代表我们的行
            for (int j =0;j<3;j++){//代表我们的列
                System.out.println(array[i][j]);
            }
        }
//        优化一下
        for (int i = 0;i<array.length;i++){//代表我们的行
            for (int j =0;j<array[i].length;j++){//代表我们的列
                System.out.println(array[i][j]);
            }
        }
        System.out.println("使用for-each来进行打印");
        for (int[] tmp:array){
            for(int x:tmp){
                System.out.println(x+" ");
            }
        }

        System.out.println("使用toString进行打印");
        System.out.println(Arrays.deepToString(array));
//
    }

    public static void reverse(int[] arr) {
        int left = 0;
        int right = arr.length-1;
        int tmp = 0;
        while (left<right){
            tmp = arr[left];
            arr[right] = tmp;
            left++;
            right--;
        }

    }
    public static void bubbleSort(int[] array) {
        //[0----len-1)i代表趟数
        for (int i = 0;i<array.length-1;i++){
            boolean flg = false;
            //j<4在这里可以不减i    减i说明是进行了优化
            for(int j=0;j<array.length-1-i;j++){
                if (array[j] > array[j+1]) {
                    int tmp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = tmp;
                    flg = true;
                }
            }
            if (flg == false) {
//                这里是判断上一次有没有进行交换,flg有没有变成true
                break;
            }
        }
//        这里还可以进一步优化,我们可以进一步添加检查,
//        检查是否发生了简化,如果没有,说明有序了,就不需要进行第三趟,第四趟...
    }


    public static void main_ArrayEqualsAndFill(String[] args) {
        int[] array1 = {1,2,3,4,5};
        int[] array2 = {1,2,3,4,5};
        boolean equal = Arrays.equals(array1,array2);
        System.out.println(equal);
        System.out.println("==============");
        int[] array = new int[10];
        System.out.println("填充之前的数组"+Arrays.toString(array));
//        结果都是0
        Arrays.fill(array,1);
        System.out.println("填充之后的数组"+Arrays.toString(array));
//        结果都是1
        Arrays.fill(array,4,10,29);
//        从[4,10)填充29

    }

    public static void main_Array(String[] args) {
        int[] array = {1,2,3,14,5};
        System.out.println("排序之前的数组:"+Arrays.toString(array));
        Arrays.sort(array);//默认升序
        System.out.println("排完序之后的数组"+Arrays.toString(array));

//index:下标,索引
        int index = Arrays.binarySearch(array,14);
        if (index == -1){
            System.out.println("没有");
        }else {
            System.out.println("下标为"+index);
        }
    }

//    二分查找,前提是查找的数组有序
    public static int binarySearch(int[] array,int key){
        int left = 0;
        int right = array.length-1;
        while (left<=right){
            int mid = (left + right) /2;
            if (array[mid]<key){
                left = mid + 1;
            }else if(array[mid]==key){
                return mid;
            }else {
                right = mid -1;
            }
        }
//        代码走到这里说明left已经大于right了,所以返回-1
        return -1;//数组没有-1
    }

    public static int search(int[] array,int key){
        for(int i=0;i<array.length;i++){
            if(array[i]==key){
                return i;
            }
        }
//        如果代码走到这里,说明推出了for循环
        return  -1;//因为数组没有负数下标
    }
    public static void main_search(String[] args) {
        int[] array = {1,2,3,4,5};
        int index = search(array,4);
        if(index == -1){
            System.out.println("没有你要找的关键字!");
        }else {
            System.out.println("找到了你要的关键字,下标是:"+ index);
        }
    }


//    求平均值
    public static double avg(int[] array) {
        int sum = 0;
        for (int i = 0;i<array.length;i++){
            sum = sum +array[i];
        }
        return sum*1.0/array.length;
//        不能 return sum/array.length
    }


    public static void main1(String[] args) {
        int[] array = {1,2,3,4,5};
        int[] ret = {1,2,3};
        ret =Arrays.copyOfRange(array,1,3);
        System.out.println(Arrays.toString(ret));
//        这里输出为[2,3]
//        因为从1下标拷贝到3下标,这里都是左闭右开的[1,3)
    }
}

到这里,数组就完结啦,后期如果有需要补充的我会另外添加,希望大佬们帮我指正~
感谢阅读!

你可能感兴趣的:(菜鸟猛啄JavaSE,java)