• 【手把手带你学JavaSE】第五篇:Java中的数组


    对了!给大家推荐一个刷题学习、面试神器——牛客网


    在这里插入图片描述

    里面有非常多的题库,跟面试经验~非常的良心!!

    一、数组的基本用法

    1.1 什么是数组?

    数组本质上就是让我们能 “批量” 创建相同类型的变量.在内存中是一段连续的空间。

    例如:

    如果需要表示两个数据, 那么直接创建两个变量即可 int a; int b

    如果需要表示五个数据, 那么可以创建五个变量 int a1; int a2; int a3; int a4; int a5;

    但是如果需要表示一万个数据, 那么就不能创建一万个变量了. 这时候就需要使用数组, 帮我们批量创建.

    注意事项: 在 Java 中, 数组中包含的变量必须是 相同类型。

    1.2 定义数组

    数组的初始化主要分为动态初始化和静态初始化
    静态初始化

    int[] arr = new int[]{1,2,3,4,5};
    double[] arr1 = new double[]{1.0,2.0,3.0,4.0,5.0};
    
    
    • 1
    • 2
    • 3

    1.静态初始化虽然没有指定数组的长度,编译器会根据{}种的个数来确定数组的个数.
    2.静态初始化可以省去后面的new 类型[ ]

    3.静态初始化时, { }中数据类型必须与[ ]前数据类型一致。

    int[] arr2 = {1,2,3,4,5};	
    //虽然省去了new 类型,但是在编译代码时会还原
    int[] arr2 = new int[]{1,2,3,4,5};	
    
    
    • 1
    • 2
    • 3
    • 4

    动态初始化

    int[] arr = new int[10];//这里动态初始10个int变量,默认为0
    
    
    • 1
    • 2

    如果数组中存储元素类型为基类类型,默认值为基类类型对应的默认值,比如:
    在这里插入图片描述
    如果数组中存储元素类型为引用类型,默认值为null

    int[] :int类型数组

    double[] :double类型数组

    通过类型就可以定义变量,比如:

    int[] array,array就是这个类型的变量,这个变量是存储一组相同数据的变量。

    三种数组定义的方式:

    在这里插入图片描述
    第一种:
    int[] array = {1,2,3,4,5,6};定义一个数组且初始化
    虽然没写new,但实际上也是一个对象

    注意事项:
    int[10] array = {1,2,3,4,5,6};写法错误,int[] 属于类型,中括号里面不能加任何的数字,相当于在这里破坏了它的类型。

    第二种:
    int[] array2 = new int[3];
    在这里插入图片描述
    定义数组未初始化

    第三种:
    int[] array3 = new int[]{1,2,3,4,5,6};
    在这里插入图片描述
    定义且初始化
    三种当中用的最多的就是第一种

    1.3 遍历数组

    所谓 “遍历” 是指将数组中的所有元素都访问一遍, 访问是指对数组中的元素进行某种操作,比如:打印。
    可以使用常见的for循环来打印数组,但首要条件是要知道数组的长度

    注意:在数组中可以通过 数组对象.length 来获取数组的长度

    1.for遍历

    public static void main(String[] args) {
            int[] arr = new int[]{1,2,3,4,5};
            for (int i = 0; i < arr.length; i++) {
                System.out.print(arr[i]+" ");
            }
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述
    2.for-each

    for-each 是 for 循环的另外一种使用方式,也叫作增强for循环,能够更方便的完成对数组的遍历. 可以避免循环条件和更新语句写错,但缺点是拿不到数组的下标

    int[] array = {1, 2, 3};
    //遍历array,每拿到一个元素,就存到x中,然后再将x打印出来
    for (int x : array) {
         System.out.println(x);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述
    3.借助Java的操作数组工具类 Arrays

    public static void main(String[] args) {
            int[] array = {1,2,3,4,5,6,7,8,9};
            String str = Arrays.toString(array);
            System.out.println(str);
            System.out.println(Arrays.toString(array));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述

    二、数组的存储

    2.1 JVM内存发布

    在这里插入图片描述
    JVM 的内存被划分成了几个区域, 如图所示:
    在这里插入图片描述
    内存是一段连续的存储空间,主要用来存储程序运行时数据的。比如:

    1. 程序运行时代码需要加载到内存
    2. 程序运行产生的中间数据要存放在内存
    3. 程序中的常量也要保存
    4. 有些数据可能需要长时间存储,而有些数据当方法运行结束后就要被销毁
    • 程序计数器 (PC Register): 只是一个很小的空间, 保存下一条执行的指令的地址
    • 虚拟机栈(JVM Stack): 重点是存储局部变量表(当然也有其他信息). 我们刚才创建的 int [ ] arr 这样的存储地址的引用就是在这里保存.
    • 本地方法栈(Native Method Stack): 本地方法栈与虚拟机栈的作用类似. 只不过保存的内容是Native方法的局部变量. 在有些版本的 JVM 实现中(例如HotSpot), 本地方法栈和虚拟机栈是一起的.
    • 堆(Heap): JVM所管理的最大内存区域. 使用 new 创建的对象都是在堆上保存 (例如前面的 new int [ ] {1, 2, 3} ),堆是随着程序开始运行时而创建,随着程序的退出而销毁,堆中的数据只要还有在使用,就不会被销毁。
    • 方法区(Method Area): 用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据. 方法编译出的的字节码就是保存在这个区域 。

    要理解数组这部分内容我们只简单关心 虚拟机栈 这两块空间即可。

    2.2 基本类型变量与引用类型变量的区别

    • 基本数据类型创建的变量,称为基本变量,该变量空间中直接存放的是其所对应的值
    • 引用数据类型创建的变量,一般称为对象的引用,其空间中存储的是对象所在空间的地址。
    int[] arr = new int[]{1,2,3,4,5};
    
    
    • 1
    • 2

    在这里插入图片描述
    **引用变量并不直接存储对象本身,可以简单理解成存储的是对象在堆中空间的起始地址。通过该地址,引用变量便可以去操作对象 。**类似于C语言中的指针,但是Java中引用要比指针的操作更简单 ,结合下面的代码进行理解:

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

    在上述代码中,a、b、arr,都是函数内部的变量,因此其空间都在main方法对应的栈帧中分配。
    a、b是内置类型的变量,因此其空间中保存的就是给该变量初始化的值。
    array是数组类型的引用变量,其内部保存的内容可以简单理解成是数组在堆空间中的首地址,当数组进行创建的时候是在堆空间中创建的对象,而array中存储数组对象的地址。

    java中的数组的内存分布要注意和C语言中的区分,不要混淆!
    在这里插入图片描述

    引用不指向对象:
    在这里插入图片描述
    因为array2=null时,array2未指向任何对象,所以不能进行任何的访问.这里出现了空指针异常
    在java中null和0地址没有关系

    一个引用能不能同时指向多个对象吗?
    在这里插入图片描述
    对于这个代码来说只能指向一个对象,存一个对象的地址。最终只保存了最后一个对象的地址

    数组作为方法的参数传递的过程:
    在这里插入图片描述
    求解打印结果:

    前两种求解:
    func1

    在这里插入图片描述
    func2
    在这里插入图片描述
    分析例子:下图代表什么
    在这里插入图片描述
    代表array2这个引用,指向了array1这个引用指向的对象。

    注意事项:
    引用指向引用这句话 是错误的,引用只能指向对象
    引用一定在栈上吗?
    不一定,一个变量在不在栈上,是你变量的性质决定的,如果你就是一个局部变量,一定是在栈上的。如果不是,例如,实例成员变量那就不一定就是在栈上的。

    三、数组在函数中的使用

    3.1 基本数据类型的传参

     public static void swap(int x,int y) {
            int h = x;
            x = y;
            y = h;
        }
        public static void main(String[] args) {
            int a = 10;
            int b = 20;
            swap(a,b);
            System.out.println("交换后 a="+a+" b="+b);
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述

    基本类型的传参,函数中改变形参,不影响实参.

    3.2 引用数据类型的传参

    public static void mul(int[] arr) {
            for (int i = 0; i < arr.length; i++) {
                arr[i]*=2;
            }
        }
        public static void main(String[] args) {
            int[] arr = new int[]{1,2,3,4,5};
            mul(arr);
            for (int x: arr) {
                System.out.print(x+" ");
            }
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在这里插入图片描述
    引用类型的传参,函数中改变形参,实参也将被改变.

    3.3 数组作为函数的返回值

    比如:获取斐波那契数列的前N项

    public class TestArray {
        public static int[] fib(int n){
            if(n <= 0){
                return null;
            } 
            
            int[] array = new int[n];
            array[0] = array[1] = 1;
            for(int i = 2; i < n; ++i){
                array[i] = array[i-1] + array[i-2];
            } 
            return array;
        }
        
        public static void main(String[] args) {
            int[] array = fib(10);
            
            for (int i = 0; i < array.length; i++) {
                System.out.println(array[i]);
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    四、数组的练习题

    4.1 交换两个变量的值

    public class TestDemo {
        public static void swap(int[] array){
            int tmp = array[0];
            array[0] = array[1];
            array[1] = tmp;
     
        }
        public static void main(String[] args) {
            int[] array = {10,20};
            System.out.println("交换前: "+array[0]+" "+array[1]);
            swap(array);
            System.out.println("交换后: "+array[0]+" "+array[1]);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    4.2 写一个方法, 将数组中的每个元素都 * 2

     /**
         * 在原来的数组上扩大2倍
         * @param array
         */
        public static void enlarge(int[] array){
            for (int i = 0; i <array.length ; i++) {
                array[i] = array[i]*2;
            }
     
        }
     
        public static void main(String[] args) {
            int[] array = {1,2,3,4,5,6,7};
            enlarge(array);
            System.out.println(Arrays.toString(array));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    4.3 模拟实现tostring函数

    public static String myToString(int[] array){
            String str = "[";
     
            for (int i = 0; i <array.length ; i++) {
                str = str+array[i];
                if(i != array.length-1){
                    str+= ",";
                }
            }
            str= str + "]";
            return str;
        }
     
        public static void main(String[] args) {
            int[] array = {1,2,3,4,5,6,7};
           String str =  myToString(array);
            System.out.println(str);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    4.4 找数组中的最大元素

        public static int maxNum(int[] array){
            if(array == null) return -1;
            if (array.length == 0) return -1;
            int max = array[0];
            for (int i = 1; i <array.length ; i++) {
                if(max < array[i]){
                    max = array[i];
     
                }
            }
            return max;
        }
     
        public static void main(String[] args) {
            int[] array = {12,8,14,26,5,7,8};
            int max = maxNum(array);
            System.out.println(max);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

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

       public static int findNum(int[] array,int key){
            for (int i = 0; i <array.length ; i++) {
                if(array[i] == key){
                    return i;
                }
            }
            return -1;
        }
     
        public static void main(String[] args) {
            int[] array = {2,4,5,6,11,7,8,9};
            System.out.println(findNum(array, 7));
     
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

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

    //二分查找的必要条件是必须有序的数列
        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){
                    right = mid - 1;
                }else if(array[mid] < key){
                    left = left + 1;
                }else{
                    return mid;
                }
     
            }
            return -1;
        }
     
        public static void main(String[] args) {
            int[] array = {12,14,15,16,18,23};
            System.out.println(binarySearch(array, 15));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    4.7 检查数组的有序性

       public static boolean isUp(int[] array){
            for (int i = 0; i <array.length-1 ; i++) {
                if(array[i]>array[i+1]){
                    return false;
                }
            }
            return true;
        }
     
        public static void main(String[] args) {
            int[] array = {12,13,14,15,16,17,18};
            System.out.println(isUp(array));
     
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    4.8 数组排序(冒泡排序)

    public class TestDemo {
        public static void bubbleSort(int[] array){
            for (int i = 0; i <array.length-1 ; i++) {
                boolean flg = false;
                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){
                    return;
                }
     
            }
        }
        public static void main(String[] args) {
            int[] array = {12,1,23,15,16,13,17};
            bubbleSort(array);
            System.out.println(Arrays.toString(array));
     
     
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    4.9 给定一个整型数组, 将所有的偶数放在前半部分, 将所有的奇数放在数组后半部分

        public static void func(int[] array){
            int i = 0;
            int j = array.length - 1;
            while(i <j){
                while(i < j && array[i] % 2 == 0){
                    i++;
                }
                while (i < j && array[j] % 2 != 0){
                    j--;
                }
                int tmp = array[i];
                array[i] = array[j];
                array[j] = tmp;
            }
        }
     
        public static void main(String[] args) {
            int[] array = {1,4,3,6,8,5,9};
            func(array);
            System.out.println(Arrays.toString(array));
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    4.10 数组的拷贝

    第一种:

      把一个数组的值拷贝到另一个数组
     public static int[] copyArray(int[] array){
            int[] copy = new int[array.length];
            for (int i = 0; i <array.length ; i++) {
                copy[i] = array[i];
            }
            return copy;
        }
     
        public static void main(String[] args) {
            int[] array = {1,4,6,3,8,9};
            int[] ret = copyArray(array);
            System.out.println(Arrays.toString(ret));
     
     
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    第二种:

    public static void main(String[] args) {
            int[] array = {1,23,4,6,8};
            int[] ret = Arrays.copyOf(array,array.length);
        }
    
    • 1
    • 2
    • 3
    • 4

    拷贝数组函数,参数:要拷贝的数组,数组的长度。
    返回值是数组类型
    还可以长度乘2,但不是在原来的基础上扩大2倍,这里是一个新的对象

    public static void main(String[] args) {
            int[] array = {1,23,4,6,8};
            int[] ret = Arrays.copyOf(array,array.length*2);
        }
    
    • 1
    • 2
    • 3
    • 4

    拷贝数组(一部分 )函数:

    public static void main(String[] args) {
            int[] array = {1,23,4,6,8};
            int[] ret = Arrays.copyOfRange(array,1,3);
        }
    
    • 1
    • 2
    • 3
    • 4

    所有的Java里面的源代码from,to都是左闭右开区间的

    第三种:

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

    在这里插入图片描述
    第一个参数是源数组,array这个数组。
    从0下标开始拷贝到哪里?给一个目的地数组copy,从0位置开始接收。
    拷多长?array数组的长度。

    第四种:
    在这里插入图片描述
    产生一个副本,调用clone函数就会产生一个一模一样的array数组

    五、二维数组

    二维数组本质上也就是一维数组, 只不过每个元素又是一个一维数组.;同理, 还存在 “三维数组”, “四维数组” 等更复杂的数组, 只不过出现频率都很低

    基本语法

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

    5.1 二维数组的创建和初始化

    • 动态初始化
    int[][] array1 = new int[2][3];
    
    • 1
    • 静态初始化
    注意:初始化时代表二维数组一行的 { } 必须给出
    int[][] array2 = new int[][]{{1,2,3},{4,5,6}};
    int[][] arrays = {{1,2,3},{4,5,6}};
    
    • 1
    • 2

    5.2 二维数组的打印

    1.深层

    public static void main(String[] args) {
            int[][] arr = new int[][]{{1,2,3},{4,5,6}};
            System.out.println(Arrays.deepToString(arr));
        }
    
    • 1
    • 2
    • 3
    • 4

    2.for循环

    public static void main(String[] args) {
            int[][] arr = new int[][]{{1,2,3},{4,5,6}};
            for (int i = 0; i < 2; i++) {
                for (int j = 0; j < 3; j++) {
                    System.out.print(arr[i][j]+" ");
                }
                System.out.println();
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3.foreach遍历

    public static void main(String[] args) {
            int[][] arr = new int[][]{{1,2,3},{4,5,6}};
            for (int[] arr1: arr) {
                for (int x: arr1) {
                    System.out.print(x+" ");
                }
                System.out.println();
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    Java二维数组的特殊化
    第一种:
    在这里插入图片描述
    第二种:
    在这里插入图片描述
    分析原因:
    在这里插入图片描述
    第三种:

    为什么Java数组的列号可以不写,因为我们可以手动指定
    在这里插入图片描述

    六、操作数组的工具类Arrays

    Arrays类位于java . util包下,是一个对数组操作的工具类, 其中包含了一些操作数组的常用方法.

    Arrays类中的方法可以分为八类:

    • sort(对数组排序)
    • binarySearch(二分法查找数组中的元素)
    • fill(对数组中的指定位置填充相同的内容)
    • copyOf(数组拷贝)
    • toString(以字符串形式输出数组)
    • asList(将数组转换为一个固定的List对象)
    • hashCode(计算数组的哈希值)
  • 相关阅读:
    Mysql——》计算日期差
    基座向量施密特正交化
    Python编程学习:深度剖析shap.datasets.adult()源码中的X,y和X_display,y_display输出数区别
    【英语:基础进阶_语法进阶提升】F3.被动语态
    Spring Boot(Vue3+ElementPlus+Axios+MyBatisPlus+Spring Boot 前后端分离)【七】
    Webpack设置代码映射,可调试打包后的代码
    NodeJS 如何连接 MongoDB
    Arduino与Proteus仿真-WiFi网络仿真环境搭建
    详谈js之面向对象
    java毕业设计百分百教育集团教务管理系统设计Mybatis+系统+数据库+调试部署
  • 原文地址:https://blog.csdn.net/weixin_61341342/article/details/126435409