【JavaSE】对于数组的理解以及实用技巧

》》》我的博客主页
》》》我的gitee链接
关注我,在学习Java的道路上共同进步!!!

Alt

Alt



数组的初始化

  1. 数组初始化的长度可以是变量,也就是数组的长度可以由自己输入。
int n = 10;
int[] arr = new int[n];//OK
  1. 如果不知道给数组初始化多大和初始化为什么值,就初始化为null。
    因为数组是引用数据类型,用来存 数组对象的地址,如果数组初始化时没有指向具体的数组对象,那就指向 null 空引用。
int[] array;
System.out.println(array);//error,使用数组的时候,数组必须已经初始化。
int[] array = null;
System.out.println(array);//OK

遍历数组

这里总结两种基本的遍历数组的方法:

public static void main(String[] args) {
    
    
    int[] array = {
    
    1, 2, 3, 4};
    //第一种遍历方式: for i循环
    for (int i = 0; i < array.length; i++) {
    
    
        System.out.print(array[i] + " ");
    }
    System.out.println();
    //第二种遍历方式:for-each循环
    for (int x:  array) {
    
    
        System.out.print(x + " ");
    }
}

前两种方法的区别就是for i循环有下标,for-each循环没有下标。

求数组的长度

格式: 数组名 . length

int[] array = {
    
    1,2,3,4};
int len = array.length;
System.out.println(len);//4

对 数组是引用数据类型 的理解

要了解数组是引用数据类型,得先了解JVM虚拟机的内存划分:
Alt

内存划分便于管理不同类型的数据。

理解数组,主要关注 虚拟机栈 以及

  • 局部变量存储在虚拟机栈中
  • 实例化的对象存储在堆中

举个例子:

public static void func() {
    
    
    int a = 10;
    int b = 20;
    int[] arr = new int[]{
    
    1, 2, 3};
}

这个代码是在func方法中创建并初始化了 3 个局部变量,这 3 个局部变量分别是 a , b 和 arr ,

变量 a 和 b 是 int 类型,也就是基本数据类型,基本数据类型创建的变量,称为基本变量,该变量空间中直接存放的是其所对应的值。所以变量 a 存放的是10,变量 b 存放的是 20;
但数组 arr 的类型是引用数据类型,而引用数据类型创建的变量,一般称为对象的引用 (引用变量),其空间中存储的是对象所在的堆内存中 的地址。所以 arr 指向数组对象的起始位置 1 。通过这个引用变量,我们可以访问和操作整型数组 arr 中的元素。Alt

Alt

Alt


再举一个例子:

public static void func2() {
    
    
     int[] array1 = new int[3];
     array1[0] = 10;
     array1[1] = 20;
     array1[2] = 30;
        
     int[] array2 = new int[]{
    
    1, 2, 3, 4, 5};
     array2[0] = 100;
     array2[1] = 200;
        
     array1 = array2;
     array1[2] = 300;
     array1[3] = 400;
     array2[4] = 500;
}

Alt
Alt
Alt
Alt

null 空引用

null ,是一个不指向对象的引用,表示一个无效的内存位置,因此不能对这个内存进行任何读写操作,一旦尝试读写, 就会抛出 NullPointerException 空指针异常。

int[] arr = null;
System.out.println(arr[0]);//error
System.out.println(arr.length);//error

数组的应用场景

  1. 保存数据
  2. 作为函数参数传递

用两段代码增强对 数组作为函数参数的理解:

第一段代码,这段代码可以通过形参改变main方法中数组对象的值:

public static void func1(int[] arr) {
    
    
    arr[0] = 99;
}

public static void main(String[] args) {
    
    
    int[] array = {
    
    1, 2, 3, 4};
    func1(array);
}

Alt
Alt
Alt

第二段代码,这段代码不能通过形参改变main方法中数组对象的值:

public static void func2(int[] arr) {
    
    
	arr = new int[]{
    
    11,22,33,44,55};
}

public static void main(String[] args) {
    
    
    int[] array = {
    
    1, 2, 3, 4};
    func2(array);
}

Alt
Alt

  1. 作为函数的返回值传递

Java当中,可以返回整个数组

public class Test {
    
    
    public static int[] func3() {
    
    
        int[] arr = new int[2];
        arr[0] = 10;
        arr[1] = 20;
        return arr;
    }
    
    public static void main(String[] args) {
    
    
        int[] ret = func3();
        for (int i = 0; i < ret.length; i++) {
    
    
            System.out.print(ret[i] + " ");//10 20
        }
    }
}

数组转字符串

使用该方法前需要导入 java.util.Arrays 包。Arrays 是操作数组的工具类,Arrays 类中包含 了一些操作数组的常用方法包。方法包可以想象成方便面的调料包,想用的时候倒调料包即可,无需关注调料包是怎么做的。
格式:Arrays.toString(需要转成字符串的数组)

import java.util.Arrays;//导入java.util.Arrays 包, 其中包含了一些操作数组的常用方法包

public class Test {
    
    
    public static void main(String[] args) {
    
    
        int[] arr = {
    
    1, 2, 3, 4, 5};
        String ret = Arrays.toString(arr);//数组转字符串
        System.out.println(ret);//[1, 2, 3, 4, 5]
    }
}

自己实现数组转字符串方法

import java.util.Arrays;

public class Test {
    
    
    public static String myToString(int[] array) {
    
    
        if(array == null) {
    
    
            return "null";
        } else if (array.length == 0) {
    
    
            return "[]";
        } else {
    
    
            String ret = "[";
            for (int i = 0; i < array.length; i++) {
    
    
                ret += array[i];
                if(i < array.length-1) {
    
    
                    ret += ", ";
                }
            }
            ret += "]";
            return ret;
        }
    }
    
    public static void main(String[] args) {
    
    
        int[] arr = {
    
    1, 2, 3, 4, 5};
        System.out.println(myToString(arr));//[1, 2, 3, 4, 5]
    }
}

数组排序

使用该方法前需要导入 java.util.Arrays 包。
整个数组升序排序格式:Arrays.sort(要被排序的数组)

import java.util.Arrays;

public class Test {
    
    
    public static void main(String[] args) {
    
    
        int[] arr = {
    
    100,345,2,564,4,10};
        Arrays.sort(arr);//整个数组升序排序
        System.out.println(Arrays.toString(arr));//[2, 4, 10, 100, 345, 564]
    }
}

数组区间升序排序格式:Arrays.sort(要被排序的数组, 下标1, 下标2)
下标1表示排序起始下标,下标2 表示排序终止下标 +1。比如在 下标1 到 下标3 的范围排序,那么格式是:Arrays.sort(数组名, 1, 4)

import java.util.Arrays;

public class Test {
    
    
    public static void main(String[] args) {
    
    
        int[] arr = {
    
    100,345,2,564,4,10};
        Arrays.sort(arr,1,4);//数组区间升序排序
        System.out.println(Arrays.toString(arr));//[100, 2, 345, 564, 4, 10]
    }
}

冒泡排序的实现

import java.util.Arrays;

public class Test {
    
    
    public static void bubbleSort(int[] array) {
    
    
        //防止空指针异常
        if(array == null) {
    
    
            return ;
        }
        
        //循环趟数,两个数要比较 1趟,3个数比较 2趟,n个数比较 n-1趟
        for (int i = 0; i < array.length - 1; i++) {
    
    
            //假设该趟已经都排序好了
            boolean flg = true;

            //每一趟的目的是该趟的所有数中,把最大的数移到最后
            //每一趟需要两两比较 array.length - 1 -i 对。
            //array.length - 1 -i中的 i 表示,该趟已经有 i 个数排序好了,不用再和最后 i 个数比较了。
            for (int j = 0; j < array.length - 1 -i; j++) {
    
    
                if(array[j] > array[j + 1]) {
    
    
                    //该趟还没有都排序好
                    flg = false;
                    //交换
                    int tmp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = tmp;
                }
            }
            //如果该趟确实已经都排序好了,结束循环
            if(flg) {
    
    
                break;
            }
        }
    }

    public static void main(String[] args) {
    
    
        int[] arr = {
    
    10, 6, 5, 2, 7};
        bubbleSort(arr);
        System.out.println(Arrays.toString(arr));//[4, 5, 6, 10, 11]
    }
}

数组逆序

Arrays 类中没有包含能逆序数组的方法,得自己实现
思路
设定两个下标, 分别指向第一个元素和最后一个元素. 交换两个位置的元素,
然后让前一个下标自增, 后一个下标自减, 循环继续即可。

import java.util.Arrays;

public class Test {
    
    
    public static void reverse(int[] array) {
    
    
        if(array == null){
    
    
            return ;
        }
        int left = 0;
        int right= array.length -1;
        while(left < right) {
    
    
            int tmp = array[left];
            array[left] = array[right];
            array[right] = tmp;
            left++;
            right--;
        }
    }

    public static void main(String[] args) {
    
    
        int[] arr = {
    
    10, 6, 5, 2, 7};
        reverse(arr);
        System.out.println(Arrays.toString(arr));//[7, 2, 5, 6, 10]
    }
}

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

Arrays 类中包含查找数组中指定元素的方法包,
使用该方法前需要导入 java.util.Arrays 包。
格式:Arrays.binarySearch(要被查找的数组, 要查找的元素)
如果没有找到该元素,会返回一个负数。

import java.util.Arrays;

public class Test {
    
    

    public static void main(String[] args) {
    
    
        int[] arr = {
    
    2, 5, 6, 7, 10};
        System.out.println(Arrays.binarySearch(arr,5));//1
    }
}

自己实现
写一个二分查找的方法,给定一个有序(有序是指升序或降序) 的整型数组,用键盘输入一个数,在数组中查找这个数,如果查到了就返回该数在数组中的下标,找不到就返回 -1。

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

  • 如果相等,即找到了返回该元素在数组中的下标
  • 如果小于,以类似方式到数组左半侧查找
  • 如果大于,以类似方式到数组右半侧查找
import java.util.Scanner;

public class Test {
    
    
    public static int binarySearch(int[] arr, int num) {
    
    
        int left = 0;
        int right = arr.length - 1;
        while(left <= right) {
    
    
            int middle = left + ((right-left) / 2);//这么算中间数是防止left + right时超出int的范围
            if(num == arr[middle]) {
    
    
                return middle;
            } else if (num > arr[middle]) {
    
    
                left = middle + 1;
            } else {
    
    
                right = middle - 1;
            }
        }
        return -1;//如果查找不到,返回-1
    }

    public static void main(String[] args) {
    
    
        int[] arr = {
    
    1, 3, 6, 7, 9, 10, 11, 13};//被查找的下标必须是升序的
        //输入要查找的数
        System.out.println("请输入要查找的数:");
        Scanner sc = new Scanner(System.in);
        int input = sc.nextInt();
        int ret = binarySearch(arr,input);

        if(ret == -1) {
    
    
            System.out.println("找不到");
        } else {
    
    
            System.out.println(input + "所在的下标是" + ret);
        }
        sc.close();
    }
}

判断两个数组的内容是否一样

Arrays 类中包含 判断两个数组的内容是否一样 的方法包,
使用该方法前需要导入 java.util.Arrays 包。
格式:Arrays.equals(数组1, 数组2)
该方法的返回类型是布尔类型

import java.util.Arrays;

public class Test {
    
    

    public static void main(String[] args) {
    
    
        int[] arr1 = {
    
    2, 6, 5, 7, 10};
        int[] arr2 = {
    
    5, 6, 7, 2, 10};
        System.out.println(Arrays.equals(arr1,arr2));//false

        int[] arr3 = {
    
    2, 6, 5, 7, 10};
        System.out.println(Arrays.equals(arr1,arr3));//true
    }
}

数组填充

Arrays 类中包含 数组填充 的方法包,
数组填充分为全部填充和部分填充
使用该方法前需要导入 java.util.Arrays 包。
全部填充格式:Arrays.fill(要填充的数组,需要填充的数)

import java.util.Arrays;

public class Test {
    
    

    public static void main(String[] args) {
    
    
        int[] arr1 = new int[10];
        Arrays.fill(arr1,9);
        System.out.println(Arrays.toString(arr1));//[9, 9, 9, 9, 9, 9, 9, 9, 9, 9]

        int[] arr2 = {
    
    3, 4, 5, 6, 7};
        Arrays.fill(arr2,8);
        System.out.println(Arrays.toString(arr2));//[8, 8, 8, 8, 8]
    }
}

部分填充格式:Arrays.fill(要填充的数组,起始下标,终止下标 + 1,需要填充的数)

import java.util.Arrays;

public class Test {
    
    

    public static void main(String[] args) {
    
    
        int[] arr2 = {
    
    3, 4, 5, 6, 7};
        Arrays.fill(arr2,0,3,8);
        System.out.println(Arrays.toString(arr2));//[8, 8, 8, 6, 7]
    }
}

数组拷贝

Arrays 类中包含 数组拷贝 的方法包,
格式;Arrays.copyOf(要拷贝的数组,拷贝长度)
返回值是一个数组,需要用数组变量接收。

import java.util.Arrays;

public class Test {
    
    

    public static void main(String[] args) {
    
    
        int[] arr = {
    
    2, 3, 4, 6};
        int[] copy = Arrays.copyOf(arr,arr.length);
        System.out.println(Arrays.toString(copy));//[2, 3, 4, 6]
    }
}

除了用来拷贝,还有扩容的作用。

import java.util.Arrays;

public class Test {
    
    

    public static void main(String[] args) {
    
    
        int[] arr = {
    
    2, 3, 4, 6};
        int[] copy = Arrays.copyOf(arr,arr.length*2);//两倍的拷贝长度
        System.out.println(Arrays.toString(copy));//[2, 3, 4, 6, 0, 0, 0, 0]
    }
}

还有一种拷贝方法,参数不是长度,而是两个坐标
格式:Arrays.copyOfRange(要拷贝的数组,起始坐标,终止坐标 + 1)

import java.util.Arrays;

public class Test {
    
    

    public static void main(String[] args) {
    
    
        int[] arr = {
    
    2, 3, 4, 6};
        int[] copy = Arrays.copyOfRange(arr,1,4);
        System.out.println(Arrays.toString(copy));//[3, 4, 6]
    }
}

以下代码不是拷贝

int[] arr = {
    
    1,2,3,4,5,6};
int[] newArr = arr;
newArr[0] = 10;

二维数组

二维数组的定义格式:

//第一种格式
int[][] array1 = {
    
    {
    
    1, 2, 3},{
    
    4, 5, 6}};
//第二种格式
int[][] array2 = new int[][]{
    
    {
    
    1, 2, 3},{
    
    4, 5, 6}};
//第三种格式
int[][] array3 = new int[2][3];

//定义不规则的二维数组,行不能省略,列可以省略
int[][] array4 = new int[2][];

二维数组的使用:
使用二维数组前,算出二维数组的列数和行数是很重要的。
二维数组是特殊的一维数组,他的每一个元素都是一维数组。

int[][] array = {
    
    {
    
    1, 2, 3},{
    
    4, 5, 6}};

System.out.println(array[0]);//地址:[I@1b6d3586
System.out.println(array[1]);//地址:[I@4554617c

System.out.println(array.length);//2,相当于行数

System.out.println(array[0].length);//3 相当于列数
System.out.println(array[1].length);//3 相当于列数

Alt
能得到二维数组的长度和宽度,就能更方便的使用二维数组了,比如遍历打印二维数组 :

int[][] array = {
    
    {
    
    1, 2, 3},{
    
    4, 5, 6}};
for (int i = 0; i < array.length; i++) {
    
    
    for (int j = 0; j < array[i].length; j++) {
    
    
        System.out.print(array[i][j] + " ");
    }
    System.out.println();
}
//输出结果:
//1 2 3 
//4 5 6

当然,用 for-each 循环就不需要求二维数组的列数和行数。

int[][] array = {
    
    {
    
    1, 2, 3},{
    
    4, 5, 6}};
//二维数组的每个元素是一维数组
for (int[] tmp : array) {
    
    
	//一维数组的每个元素才是整型
    for (int x: tmp) {
    
    
        System.out.print(x + " ");
    }
    System.out.println();
}
//输出结果:
//1 2 3 
//4 5 6

二维数组转字符串

Arrays工具类中包含的 Arrays.deepToString() 方法可以将二维数组转字符串
格式:Arrays.deepToString(数组名)

int[][] array = {
    
    {
    
    1, 2, 3},{
    
    4, 5, 6}};
System.out.println(Arrays.deepToString(array));// [[1, 2, 3], [4, 5, 6]]

不规则二维数组的使用

不规则二维数组没有初始化的时候每个元素都是 null ,不指向任何一个一维数组,当对 null 进行读写操作时就会出现空指针异常(NullPointerException)

int[][] array = new int[2][];
System.out.println(array[0]);//null
System.out.println(array[1]);//null
for (int i = 0; i < array.length; i++) {
    
    
    for (int j = 0; j < array[i].length; j++) {
    
    //空指针异常,因为不能对空引用进行读写操作
       System.out.print(array[i][j] + " ");
    }
    System.out.println();
}

对二维数组的每个元素创建一个数组之后是可以使用的。

public static void main(String[] args) {
    
    
int[][] array = new int[2][];
array[0] = new int[]{
    
    1,2};
array[1] = new int[]{
    
    1,2,3,4};
        
for (int i = 0; i < array.length; i++) {
    
    
    for (int j = 0; j < array[i].length; j++) {
    
    
        System.out.print(array[i][j] + " ");
    }
    System.out.println();
}
//输出结果:
//1 2 
//1 2 3 4 

猜你喜欢

转载自blog.csdn.net/weixin_73276255/article/details/131996247