Skip to content

数组

基本使用

概念

概念:一组连续的存储空间,存储多个相同数据类型的值,长度是固定的。

定义

java
方式1:先声明、再分配空间
数据类型[] 数组名;
数组名 = new 数据类型[长度];

方式2:声明并分配空间:
数据类型[] 数组名 = new 数据类型[长度];

方式3:声明并赋值(繁):
数据类型[] 数组名 = new 数据类型[]{value1,value2,value3,...};

方式4:声明并赋值(简):
数据类型[] 数组名 = {value1,value2,value3,...};
java
package com.yuluo;

public class ArrayTrain {
    public static void main(String[] args) {
        String [] userNameArr = new String[3];
        int [] ageArr = new int[3];
        // 赋值
        ageArr[0] = 18;
        userNameArr[0] = "Hanser";
        // 取值
        System.out.println("年龄为:"+ageArr[0]);
        System.out.println("姓名为:"+userNameArr[0]);
    }
}

使用

数组的元素:数组中的每个数据称之为数组中的元素

数组的访问:对数组中的元素赋值以及取值的操作 统称为数组的访问

下标、索引、角标、index : 下标自动生成 从0开始 往后依次+1

java
访问数组通过下标访问:
赋值  数组名[下标] = 值;
取值  System.out.println(数组名[下标]);
访问不存在的下标 将会导致数组下标越界异常  ArrayIndexOutOfBoundsException
java
package com.yuluo;

public class ArrayTrain {
    public static void main(String[] args) {
        String [] userNameArr = new String[3];
        int [] ageArr = new int[3];
        // 赋值
        ageArr[0] = 18;
        userNameArr[0] = "Hanser";
        // 取值
        System.out.println("年龄为:"+ageArr[0]);
        System.out.println("姓名为:"+userNameArr[0]);
    }
}

遍历

数组的遍历:逐一对数组中的元素进行访问 称之为数组的遍历

java
package com.yuluo;

public class ArrayTrain {
    public static void main(String[] args) {
        // 定义一个数组
        int[] age;
        age = new int[3];
        // 数组的遍历
        for (int i = 0; i < age.length; i++) {
            // 赋值
            age[i] = i;
        }
        // 数组遍历
        for (int i = 0; i < age.length; i++) {
            System.out.println(age[i]);
        }
    }
}

默认值

数组的默认值:数组作为引用数据类型 其元素是有默认值的 当我们给数组开辟空间以后 默认值即存在

java
整数:0
浮点:0.0
字符:\u0000
布尔:false
其他:null (空)
java
package com.yuluo;

import java.util.Arrays;

public class ArrayTrain {
    public static void main(String[] args) {
        // 定义一个数组
        int[] age = new int[3];
        byte[] sex = new byte[2];
        float [] salary = new float[3];
        boolean [] leader = new boolean[2];
        String [] name = new String[2];
        char [] marriage= new char[2];
        // 把数组转为String
        String ageStr = Arrays.toString(age);
        String sexStr = Arrays.toString(sex);
        String leaderStr = Arrays.toString(leader);
        String nameStr = Arrays.toString(name);
        String salaryStr = Arrays.toString(salary);
        String marriageStr = Arrays.toString(marriage);
        // 打印String
        System.out.println(ageStr); // [0, 0, 0]
        System.out.println(sexStr); // [0, 0]
        System.out.println(salaryStr); // [0.0, 0.0, 0.0]
        System.out.println(marriageStr); // /u0000
        System.out.println(leaderStr); // [false, false]
        System.out.println(nameStr); // [null, null]
    }
}

使用一个为null的对象,调用任何属性或者方法,都将出现空指针异常

扩容

背景:创建数组时,必须显式指定长度,并在创建之后不可更改长度。

数组的扩容

ts
实现步骤:
    1.创建比原数组更长的新数组
    2.将原数组中的元素依次复制到新数组中
    3.将新数组的地址赋值给原数组

注意:

数组作为引用数据类型 其数组名中保存的是指向堆中的地址

所以 当我们把一个数组 赋值 给 另外一个数组时 赋值的是堆地址

默认打印数组本身得到的是一个内存中的堆地址

image-20250220153511317

java
package com.yuluo;

import java.util.Arrays;

public class ArrayTrain {
    public static void main(String[] args) {
        // 数组扩容
        int [] oldArr = {15,16,17,18};
        // 创建比之前大的新数组
        int [] newArr = new int [oldArr.length * 2];
        // 复制新数组
        for (int i = 0; i < oldArr.length; i++) {
            newArr[i] = oldArr[i];
        }
        // 地址替换
        oldArr = newArr;
        // 设置新数组
        newArr[7] = 28;
        System.out.println(oldArr);// [I@4554617c
        System.out.println(newArr); // [I@4554617c
        System.out.println(Arrays.toString(newArr)); // [15, 16, 17, 18, 0, 0, 0, 28]
    }
}

复制

复制数组的三种方式:

​ 循环将原数组中所有元素逐一赋值给新数组。

System.arraycopy(原数组,原数组起始,新数组,新数组起始,长度); 无返回值

java.util.Arrays.copyOf(原数组, 新长度); 有返回值,返回带有原值的新数组。

java
package com.yuluo;

import java.util.Arrays;

public class copyArray {
    public static void main(String[] args) {
        int [] oldArr = {12,13,14,15};
        int [] newArr = new int[10];
        int [] ageArr = {13,13,13};
        // 1. 使用 System.arraycopy 方法
        // 参数为 旧数组 下标 新数组 下标 长度
        // 无返回值
        System.arraycopy(oldArr,1,newArr,2,2);
        System.out.println("新数组为 " + Arrays.toString(newArr));
        // 2. 使用 Arrays.copyOf 方法
        // 有返回值
        int [] newAgeArr = Arrays.copyOf(ageArr,10);
        System.out.println("新数组1为 " + Arrays.toString(newAgeArr));
    }
}

数组方法

JDK提供了一个用于操作数组的工具类 java.util.Arrays,此类中提供大量的用于操作数组的各种方法

类的方法 类似JS中类本身的方法

ts
Arrays.toString(数组名) : 将数组中的元素转换为字符串 返回
Arrays.copyOf(数组名,新长度) : 复制数组,存在返回值
Arrays.sort(数组名) : 将数组按照升序排序  属于快速排序 实现原理为 递归
Arrays.fill(数组名,填充元素) : 将数组按照指定元素进行填充
Arrays.binarySearch(数组名,元素) : 使用二分查找法查找某个元素在数组中的下标(前提是数组是升序排序后的,且元素不重复),返回值为下标

案例

java
package com.yuluo;

import java.util.Arrays;

public class utilsArray {
    public static void main(String[] args) {
        int [] nums = {56,12,22,41,85,99};
        // 使用 sort方法排序:快速排序 默认是升序
        Arrays.sort(nums);
        System.out.println(Arrays.toString(nums)); // [12, 22, 41, 56, 85, 99]

        int [] newArr = new int[nums.length];
        // 降序排序
        for (int i = 0,j = nums.length -1; i < nums.length; i++,j--) {
            newArr[i] = nums[j];
        }
        System.out.println(Arrays.toString(newArr)); // [99, 85, 56, 41, 22, 12]
        // 填充元素
        Arrays.fill(newArr,445);
        System.out.println(Arrays.toString(newArr)); // [445, 445, 445, 445, 445, 445]

        // 查找元素
        int index = Arrays.binarySearch(nums, 41);
        System.out.println("查找到的下标为"+index); // 查找到的下标为 2
    }
}

数组属性

数组的属性:length属性 表示数组的长度 是一个int类型的整数 可以通过数组名.length获取

类似于JS中 实例的方法

ts
arr.length  返回数组的长度
java
package com.yuluo;

public class ArrayTrain {
    public static void main(String[] args) {
        // 定义一个数组
        int[] age;
        age = new int[3];
        // 数组的遍历
        for (int i = 0; i < age.length; i++) {
            // 赋值
            age[i] = i;
        }
    }
}

插入(删除)元素

可以使用System.arraycopy方法 实现插入效果

案例:编写方法实现在数组中删除元素

java
public class delArrayEle {
    public static void main(String[] args) {
        int [] nums = {1,2,3,4,5};
        // 调用删除方法 删除下标 为2
        int[] delete = delete(nums,2);
        System.out.println(Arrays.toString(delete));
    }

    // 删除元素 旧数组 下标
    public static int[] delete(int[] oldArray, int index) {
        if (index < 0 || index > oldArray.length) {  
            // 判断下标 如果小于0 或者 大于等于数组长度 表示不合法 因为删除 只能删除有效范围以内的
            System.out.println("下标非法");
            return oldArray; // 直接将传入的原数组返回 表示没有做任何操作
        }
        // 准备一个长度-1的数组 用于删除之后复制元素
        int[] newArray = new int[oldArray.length - 1];
        // 循环遍历开始复制元素
        for (int i = 0; i < newArray.length; i++) {
            if (i < index) { // 情况1 小于删除的下标 直接复制
                newArray[i] = oldArray[i];
            } else {  // 情况2 大于等于删除下标 则直接将原数组的+1位置 移动到新数组的后续位置 属于向左移动覆盖
                newArray[i] = oldArray[i + 1];
            }
        }
        return newArray; // 将新数组返回
    }

}

案例:编写方法实现在数组中插入元素

java
package com.yuluo;

import java.util.Arrays;

public class insertArrayEle {
    public static void main(String[] args) {
        int [] nums = {1,2,3,4,5};
        // 方法
        int[] newArray = insertArray(nums, 2,18);
        System.out.print(Arrays.toString(newArray));
    }
    // 插入元素的方法
    public static int[] insertArray(int [] oldArrays,int index,int val){
        // 下标不能小于0 或者 不能大于数组的长度
        if(index < 0 || index > oldArrays.length){
            System.out.println("下标不合法");
            // 如果下标不合法 则将传入的数组 直接返回 表示没有做任何操作
            return oldArrays;
        }
        // 准备一个长度+1的数组 用于插入元素
        int [] newArray = new  int[oldArrays.length + 1];
        // 遍历开始移动元素
        for(int i = 0;i < oldArrays.length;i++){
            // 情况1 小于插入下标 则直接复制到新数组中
            if(i < index){
                newArray[i] = oldArrays[i];
            }else{ // 情况2  大于或者等于插入下标 则移动到新数组的+1位置
                newArray[i + 1] = oldArrays[i];
            }
        }
        // 空缺位插入指定的元素
        newArray[index] = val;
        return newArray; // 将新数组返回
    }
}

可变长参数

可变长参数:可接收多个同类型实参,个数不限,使用方式与数组相同。

ts
要求:

1.整个形参列表中只能有一个可变长参数
2.必须书写在形参列表的末尾

格式:数据类型...参数名

底层实现是数组
java
package com.yuluo;

public class ChangeAbleParams {
    // 可变长参数
    public static void funChangeParams (int ... args) {
        System.out.println("fun方法执行");
        for (int i = 0; i < args.length; i++) {
            System.out.println(args[i]);
        }
    }

    // 数组类型的参数
    public static void funArrayTypeParams(int [] args){
        System.out.println("funArray方法执行");
        for (int i = 0; i < args.length; i++) {
            System.out.println(args[i]);
        }
    }
    public static void main(String[] args) {
        // 第一个方法调用
        funChangeParams(12,13,14,15);
        // 第二个方法调用
        int [] nums = {13,14,15,16};
        funArrayTypeParams(nums);
    }
}

数组应用

冒泡排序(写)

它重复地遍历要排序的数组,比较相邻的元素,并交换它们的位置,直到整个数组有序为止。

java
数组的数量:n
比较的轮数为:n - 1
每一轮比较的次数:n - 1 - ?

外层循环控制比较的轮数:n - 1
内存循环控制每一轮比较的次数:n - 1 - i
java
package com.yuluo;

public class ShortArray {
    public static void main(String[] args) {
        int [] arr = {64, 34, 25, 12, 22, 11, 90};
        System.out.println("排序前的数组:");
        printArray(arr);
        // 排序
        Bubble(arr);
        // 打印排序后的数组
        System.out.println("排序后的数组:");
        printArray(arr);
    }
    // 冒泡排序
    public static void Bubble(int [] arr){
        int length = arr.length;
        boolean swapped;
        for(int i = 0;i < length -1;i++){
            swapped = false;
            for(int j = 0; j< length -1 -i;j++){
                if(arr[j]>arr[j+1]){
                    // 交换 arr[j] 和 arr[j+1]
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                    swapped = true;
                }
            }
            // 如果没有发生交换
            if(!swapped){
                break;
            }
        }
    }
    // 打印数组
    public static void printArray(int[] arr) {
        for (int i :arr){
            System.out.print(i+" ");
        }
        System.out.println();
    }
}

选择排序

固定值与其他值依次比较大小,互换位置。

选择排序:固定位置的元素与其他元素依次比较大小,遇到需要交换位置的元素,先不交换,使用应该被交换位置的元素继续往后比较,等待一轮比较完成,统一交换一次位置。

java
数组的数量:n
比较的轮数为:n - 1
每一轮比较的次数:最多的一次为n - 1 后续每一轮递减1

将外层循环作为比较的元素A 从第一个元素开始 到 倒数第二个元素
将内层循环作为比较的元素B 从第二个元素开始 到 最后一个元素(即每一轮都是从比较的元素A 紧邻的后边的位置开始)
    
选择排序每一轮最多只会交换一次位置 所以即使每一轮都交换位置 也最多交换长度的减1次 因为轮数为长度的减1轮
java
package com.yuluo;

import java.util.Arrays;

public class SelectSort {
    public static void main(String[] args) {
        int[] nums = {-2, 562, -1, 451, 110, 23, 45, 85, 96, 666};
        int count = 0;
        int length = nums.length;
        for (int i = 0; i < length - 1; i++) { // A
            int index = i; // 定义moveIndex 表示为需要最终交换位置的下标
            for (int j = i + 1; j < length; j++) { // B
                if (nums[index] > nums[j]) {
                    // 如果A > B,把J的下标赋值给index,拿着B去找下一个B比较,直到这一轮比较结束
                    index = j;
                }
            }
            // 如果moveIndex 和 i的值不相同 则表示需要交换元素
            // 因为 只有比较大小的条件成立 moveIndex的值 才会发生变化
            // 而条件成立 则表示有需要交换位置的元素
            // 最终将moveIndex 和 i 对应位置的元素进行交换 因为
            // i 表示每一轮的第一个元素 而moveIndex最终将停留在最大/最小的元素
            if (index != i) {
                int temp = nums[i];
                nums[i] = nums[index];
                nums[index] = temp;
                count++;
            }
        }
        System.out.println(Arrays.toString(nums));
        System.out.println("一共交换了" + count + "次位置");
    }
}

数组平均值

java
package com.yuluo;

import java.util.Scanner;

public class ArrayTypeParams {
    public static void main(String[] args) {
        // 统计int类型数组中的所有元素总和 平均值
        Scanner input = new Scanner(System.in);
        System.out.println("输入数组的长度");
        // 输入
        int length = input.nextInt();
        // 创建数组
        int [] nums = new int[length];
        // 定义sum
        int sum = 0;
        for (int i = 0; i < nums.length; i++) {
            System.out.println("请输入第"+ ( i + 1)+ "个元素");
            // 输入元素
            nums[i] = input.nextInt();
            // 做累加计算
            sum += nums[i];
        }
        // 打印输出
        System.out.println("数组的总和为"+sum);
        System.out.println("数组的平均值为"+sum/nums.length);
    }
}

数组最值

ts
// 分析:先假设一个最大值/最小值 依次与其他元素进行比较 如果遇到更大的/更小的 就交换

package com.yuluo;

import java.util.Scanner;

public class ArrayTypeParams {
    public static void main(String[] args) {
        // 数组最值问题
        // 分析:先假设一个最大值/最小值 依次与其他元素进行比较 如果遇到更大的/更小的 就交换
        Scanner input = new Scanner(System.in);
        System.out.println("输入数组长度");
        int length = input.nextInt();
        int [] numArr = new int[length];
        // 输入数组元素
        for (int i = 0; i < numArr.length; i++) {
            System.out.println("输入第"+(i+1)+"个数组元素");
            numArr[i] = input.nextInt();
        }
        // 假设第一个为最大值
        int max = numArr[0];
        int min = numArr[0];
        for (int i = 1; i < numArr.length; i++) {
            // 比较最大值
            if(numArr[i] > max){
                // 如果大于最大值,则替换最大值
                max = numArr[i];
            }
            // 比较最小值
            if(numArr[i] < min){
                // 如果大于最大值,则替换最大值
                min = numArr[i];
            }
        }
        System.out.println("最大的元素为:" + max);
        System.out.println("最小的元素为:" + min);
    }
}

值传递

java
值传递和引用传递的区别?
    Java官方明确指出 Java中只有值传递
    基本数据类型属于'值传递',传递的就是值的副本,值的拷贝,在方法中对参数的修改不会影响原变量
    引用数据类型属于'引用传递' 传递的是地址,也就是引用,在方法中对参数的修改会影响原变量
    String类型是特殊的引用数据类型 作为参数不会影响原变量 因为String是不可变对象
java
package com.yuluo;

import java.util.Arrays;

public class ValuePass {
    // 值传递和引用传递的区别?
    public static void fun(int num){
        num++;
    }
    public static void fun2(int [] nums){
        for (int i = 0; i < nums.length; i++) {
            nums[i]++;
        }
    }

    public static void main(String[] args) {
        int a = 10;
        // 调用fun:基本数据类型 参数传递的是值
        fun(a);
        System.out.println("a = " + a); // 10 修改的是num a的值并没有发生改变
        // 调用fun2:引用数据类型 参数传递的值地址
        int [] b = {1,2,3,4};
        fun2(b);
        System.out.println("b = "+ b); // b = [I@4554617c
        System.out.println("b的值为"+ Arrays.toString(b)); // b的值为[2, 3, 4, 5]
    }
}

二维数组

二维数组:数组中的元素还是数组

二维数组定义:和一维数组定义方式大致相同

二维开辟空间 高维度(第一个中括号)长度必须指定 低维度(第二个中括号)长度可以后续单独指定

java
package com.yuluo;

public class twoDimeArray {
    public static void main(String[] args) {
        // 定义一维数组
        int [] arr1 = {1,2,3,4,5};
        // 定义二维数组
        int [][] arr2 = {{1,2,4},{16,17,18}};
        // 打印二维数组中内层
        System.out.println(arr2[0]); // [I@4554617c
        System.out.println(arr2[0][2]); // 4
        //
        for (int i = 0; i < arr2.length; i++) {
            System.out.println(arr2[i]); // 全部是内存地址
            for (int j = 0; j < arr2[i].length; j++) {
                System.out.print(arr2[i][j] + "\t"); // 1	2	4
            }
            System.out.println();
        }

    }
}

二维数组的定义案例

java
package com.atguigu.test3;

/**
 * @author WHD
 * @description TODO
 * @date 2023/8/4 15:38
 *  二维数组定义:和一维数组定义方式大致相同
 *  二维开辟空间 高维度(第一个中括号)长度必须指定 低维度(第二个中括号)长度可以后续单独指定
 */
public class Test2DArrayDefine {
    public static void main(String[] args) {
        // 方式1
        int [][] arr1;
        arr1 = new int[3][4];

        // 方式2
        // 数组的默认值 二维数组每个元素为一维数组 属于引用数据类型 其默认值为null
        // 当我们创建一个长度为2的二维数组 表示在内存中 有两个一维数组 都指向为null
        int [][] arr2 = new int[2][];

        System.out.println(arr2[0]); // null
        System.out.println(arr2[1]); // null

        arr2[0] = new int[3];
        arr2[0][0] = 11;
        arr2[0][1] = 11;
        arr2[0][2] = 11;

        arr2[1] = new int[2];
        arr2[1][0] = 34;
        arr2[1][1] = 56;

        // 方式3
        int [][] arr3 = new int[][]{{1},{22,33,44},{55,55,666}};

        // 方式4
        int [][] arr4 = {{1},{22,33,44},{55,55,666}};
    }
}

杨辉三角案例

java

package com.yuluo;
/**
 *  杨辉三角
 *  1
 *  1   1
 *  1   2   1
 *  1   3   3   1
 *  1   4   6   4   1
 *  1   5   10  10  5   1
 */
public class YangHuiTri {
    public static void main(String[] args) {
        // 定义一个 6*6 的矩阵
        int [][] yh = new int[6][6];
        // 遍历 赋值
        for (int i = 0; i < yh.length; i++) {
            yh[i][0] = 1; // 每一行的第一列为1
            yh[i][i] = 1; // 每一行的第i列为1
            if(i > 1){ // 表示从第3行开始 赋值有具体的计算
                for (int j = 1; j < i; j++) {
                    yh[i][j] = yh[i-1][j] + yh[i-1][j-1];
                }
            }
        }
        // 遍历 打印
        for(int i = 0;i < yh.length;i++){
            for(int j = 6;j > i;j--){
                System.out.print(" "); // 打印一个倒三角形
            }
            for(int j = 0;j <= i;j++){  // 打印
                System.out.print(yh[i][j] + " ");
            }
            System.out.println();
        }
    }
}