Java数组


Java 数组

一、数组介绍

数组指的是一种容器,可以用来存储同种数据类型的多个值。

那么为什么要使用数组呢?

在销售部门中,如果我们想要对部门中销售情况进行分析,我们凭借基本数据类型中的 int 类型也可以实现,但是人数多的话,就需要创建多个变量,但这样感觉特别复杂,光是想变量名就感觉头疼,但如果使用数组,我们可以把数据通过简短的代码对数据进行存储。

image-20230124182408178

使用思路

今后若要操作的多数据,属于同一组数据就可以考虑使用数组容器进行维护

image-20230124184038781

二、数组

1. 数组静态初始化

1.1 数组定义格式
  • 格式一:数据类型[ ] 数组名
  • 范例:int[ ] array
  • 格式二:数据类型 数组名[ ]
  • 范例:int array[ ]

下面我们通过一个案例来学习数组的定义格式:

package cn.edu.hgu.array;

public class ArrayDemo1 {
    public static void main(String[] args) {
        int[] arr1;
        int arr2[];
    }
}

注意:这种定义格式,定义出来的,只是数组类型的变量而已,内存中还没有创建出数组容器。

1.2 数组静态初始化

初始化:就是在内存中,为数组容器开辟空间,并将数据存入容器中的过程。

image-20230124184222438

完整格式:

数据类型[] 数组名 = new 数据类型[] { 元素1,元素2,元素3};
范例:
int[] array = new int[]{ 112233 };
double[] array2 = new double[] { 11.122.233.3};

相对于完整格式,我们更常用的是简化格式:

数据类型[] 数组名 = { 元素1,元素2,元素3};
范例:
int[] array = { 112233 };
double[] array2 = { 11.122.233.3};

下面我们使用简化格式来定义数组并打印数组名:

package cn.edu.hgu.array;

public class ArrayDemo1 {
    public static void main(String[] args) {
        int[] array1 = {11, 22, 33};
        System.out.println(array1);

        double[] array2 = {44.4, 55.5, 66.6};
        System.out.println(array2);
    }

}

输出结果为:

image-20230124191518867

输出结果并不是我们期望的数值,而是一串字符,下面我们来分析一下:

  • @:分隔符
  • [:当前空间是数组类型的
  • I:当前数组类型,是 int 类型
  • 4eec7777:数组的16进制内存地址

得出结论:打印数组名, 会看到数组在内存中的十六进制地址值

2. 数组元素访问

格式:

数组名[索引];

索引:索引是数组容器中空间的编号,编号从0开始,逐个+1增长

下面我们创建一个数组并进行访问:

package cn.edu.hgu.test;

public class ArrayTest1 {
    public static void main(String[] args) {
        arrayTest();
    }

    public static void arrayTest() {
        int[] arr = {11, 22, 33, 44, 55};
        // 取出数组中 22 元素,打印在控制台
        System.out.println(arr[1]);

        // 判断数组中第一个元素是奇数还是偶数
        if (arr[0] % 2 == 0) {
            System.out.println(arr[0] + "是一个偶数");
        } else {
            System.out.println(arr[0] + "是一个奇数");
        }

        //修改数组中第三个元素为 66
        arr[2] = 66;
        System.out.println(arr[2]);

        // 根据数组中第四个元素,决定在控制台打印多少次 HelloWorld
        for (int i = 1; i <= arr[3]; i++) {
            System.out.println("HelloWorld");
        }
    }
}

输出结果为:

image-20230124193145059

3. 数组遍历操作

3.1 数组遍历介绍

数组遍历:将数组中所有的内容取出来,取出来之后可以(打印,求和,判断…)

image-20230124193229804

下面我们通过案例来说明,如何遍历一个数组:

package cn.edu.hgu.test;

public class ArrayTest2 {
    public static void main(String[] args) {
        printArray();
    }
    /*
        数组遍历
     */
    public static void printArray(){
        int[] arr = {11,22,33,44,55};

        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }
}

输出结果为:

image-20230124200757320

数组遍历快捷键:数组名.fori

3.2 数组遍历场景

那么,什么时候需要使用数组遍历呢?

如果要完成的需求,是需要操作到数组中的【每一个】元素,就需要对数组进行遍历操作

3.3 数组遍历案例
1)数组遍历-求偶数和
package cn.edu.hgu.test;

public class ArrayTest3 {
    public static void main(String[] args) {
        getSum();
    }

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

        // 1.定义求和变量,准备进行累加操作
        int sum = 0;
        // 2.遍历数组,获取到每一个元素
        for (int i = 0; i < arr.length; i++) {
            // 3.判断当前元素是否为偶数
            if (arr[i] % 2 == 0) {
                // 4.是的话,进行累加求和
                sum += arr[i];
            }
        }
        // 5.遍历结束后,将求和结果打印
        System.out.println("偶数和为:" + sum);
    }
}

输出结果为:

image-20230124210406246

2)数组遍历-求最大值

需求:已知数组元素为 {5,44,33,55,22} ,请找出数组中最大值并打印在控制台

image-20230124210606785

分析:

  • 定义 max 变量来记录擂台上不断变化的数据
  • 数组中 0 号选手先上台,因此 int max = arr[0];
  • 遍历数组取出每一个元素,索引从 1 开始
  • 逐个进行比较,找到更大的,max变量记录更大的数据
  • 遍历后打印 max 变量所记录的值

代码实现:

package cn.edu.hgu.test;

public class ArrayTest4 {
    public static void main(String[] args) {
        int[] arr1 = {33, 55, 11, 22, 44};
        int[] arr2 = {100, 99, 66, 88, 77};

        int max = getMax(arr2);
        System.out.println("最大值为:" + max);
    }

    public static int getMax(int[] arr) {
        int max = arr[0];

        for (int i = 1; i < arr.length; i++) {
            if (arr[i] > max) {
                max = arr[i];
            }
        }
        return max;
    }

}

输出结果为:

image-20230124211306015

3)数组遍历综合案例

需求:已知班级学生成绩为 Int[ ] arr ={100,50,20,90,90};

  1. 找出数组最大值,并打印在控制台
  2. 找出数组最小值,并打印在控制台
  3. 求总成绩,并打印在控制台
  4. 计算出平均值,并打印在控制台
  5. 统计出低于平均值元素的个数

代码实现:

package cn.edu.hgu.test;

public class ArrayTest5 {
    public static void main(String[] args) {
        int[] arr = {100, 50, 20, 90, 90};

        int max = getMax(arr);
        System.out.println("最高分为:" + max);

        int min = getMin(arr);
        System.out.println("最低分为:" + min);

        int sum = getSum(arr);
        System.out.println("班级总成绩:" + sum);

        double avg = getAvg(arr);
        System.out.println("班级平均分为:"+avg);

        int count = getCount(arr);
        System.out.println("低于平均分的人数为:"+count);


    }
    /**
     * 统计出低于平均值元素的个数
     */
    public static int getCount(int[] arr){
        int count = 0;
        double avg =getAvg(arr);

        for (int i = 0; i < arr.length; i++) {
            if (arr[i]<avg){
                count++;
            }
        }
        return count;
    }

    /**
     * 计算出平均值,并打印在控制台
     */
    public static double getAvg(int[] arr){
        double sum = getSum(arr);
        double avg = sum/arr.length;
        return avg;
    }
    /**
     * 求总成绩,并打印在控制台
     */
    public static int getSum(int[] arr) {

        // 1.定义求和变量,准备进行累加操作
        int sum = 0;
        // 2.遍历数组,获取到每一个元素
        for (int i = 0; i < arr.length; i++) {
            // 3.判断当前元素是否为偶数
            if (arr[i] % 2 == 0) {
                // 4.是的话,进行累加求和
                sum += arr[i];
            }
        }
        // 5.遍历结束后,将求和结果返回
        return sum;
    }

    /**
     * 找出数组最大值,并打印在控制台
     */
    private static int getMax(int[] arr) {
        int max = arr[0];

        for (int i = 1; i < arr.length; i++) {
            if (arr[i] > max) {
                max = arr[i];
            }
        }
        return max;
    }

    /**
     * 找出数组最小值,并打印在控制台
     */
    private static int getMin(int[] arr) {
        int min = arr[0];

        for (int i = 1; i < arr.length; i++) {
            if (arr[i] < min) {
                min = arr[i];
            }
        }
        return min;
    }

}

输出结果为:

image-20230124214351184

4. 数组动态初始化

4.1 数组动态初始化介绍

动态初始化:初始化时只指定数组长度,由系统为数组分配初始值

格式:

数据类型[] 数组名 = new 数据类型[数组长度];

范例:

int[] arr  = new int[3];

那么我们知道了动态初始化的格式,那不同数据类型的初始值是一样的吗?下表是不同数据类型对应的默认值:

image-20230125084804752

下面我们来使用一下数组动态初始化方法:

package cn.edu.hgu.array;

public class ArrayDemo2 {
    public static void main(String[] args) {
        arrayTest();
    }

    public static void arrayTest() {
        //整数
        int[] arr1 = new int[3];

        for (int i = 0; i < arr1.length; i++) {
            System.out.println(arr1[i]);
        }
        System.out.println("--------------");

        //小数
        double[] arr2 = new double[3];

        for (int i = 0; i < arr2.length; i++) {
            System.out.println(arr2[i]);
        }
        System.out.println("--------------");

        //字符
        char[] arr3 = new char[3];
        for (int i = 0; i < arr3.length; i++) {
            System.out.println(arr3[i]);
        }
        System.out.println("--------------");

        //布尔
        boolean[] arr4 = new boolean[3];
        for (int i = 0; i < arr4.length; i++) {
            System.out.println(arr4[i]);
        }
        System.out.println("--------------");

        //字符串
        String[] arr5 = new String[3];
        for (int i = 0; i < arr5.length; i++) {
            System.out.println(arr5[i]);
        }

    }

}

输出结果为:

image-20230124215804518

通过上面的练习,我们了解了不同数据类型对应不同的初始值。

4.2 两种初始化的区别
  • 动态初始化:手动指定数组长度,由系统给出默认初始化值。
  • 静态初始化:手动指定数组元素,系统会根据元素个数,计算出数组的长度

使用场景:

  1. 静态初始化:如果要操作的数据,需求中已经明确出了,直接静态初始化

    需求:已知班级学生成绩为 100 100 90 20 100,找出最高分

    int[ ] arr = {100,100,90,20,100}

  2. 动态初始化:只明确元素个数,不明确具体数值

    需求1:键盘录入 5 个学生成绩,找出最高分

    需求2:产生10个1~100之间的随机数,找出最小值

4.3 数组动态初始化案例
1)使用键盘录入填充数组

需求:键盘录入5个整数并求出最大值

分析:

  1. 动态初始化数组,长度指定为5
  2. 循环遍历数组,在遍历的过程中,键盘录入整数并存入数组
  3. 求出数组最大值
  4. 打印数组

代码如下:

package cn.edu.hgu.test;

import java.util.Scanner;

import static cn.edu.hgu.test.ArrayTest4.getMax;

public class ArrayTest6 {
    public static void main(String[] args) {
        int[] arr = initArrayFromScanner();

        int max = getMax(arr);
        System.out.println("最大值为:" + max);
    }

    private static int[] initArrayFromScanner() {
        Scanner sc = new Scanner(System.in);
        System.out.println("键盘录入班级成绩,请输入班级人数");
        int count = sc.nextInt();
        int[] arr = new int[count];

        for (int i = 0; i < arr.length; i++) {
            System.out.println("请输入第" + (i + 1) + "个元素");
            arr[i] = sc.nextInt();
        }
        return arr;
    }
}

输出结果为:

image-20230125090110830

思路积累:

如果只明确元素个数,不明确具体数值可以考虑使用动态初始化,将容器准备好,随后再对容器进行填充

2)使用随机数填充数组

需求:产生10个1-100之间的随机数,并找出最大值

分析:

  1. 动态初始化数组,长度指定为10
  2. 循环遍历数组,在遍历的过程中,产生随机数并存入数组
  3. 遍历打印出数组现有元素
  4. 求出最大值
  5. 打印最大值

代码实现:

package cn.edu.hgu.test;

import java.util.Random;

import static cn.edu.hgu.test.ArrayTest4.getMax;

public class ArrayTest7 {
    public static void main(String[] args) {
        int[] randomNums = new int[10];
        Random r = new Random();

        for (int i = 0; i < randomNums.length; i++) {
            randomNums[i] = r.nextInt(100) + 1;
            System.out.println(randomNums[i]);

        }

        int max = getMax(randomNums);
        System.out.println("最大值为:" + max);
    }


}

输出结果为:

image-20230125112947924

5. 数组内存图

5.1 Java 内存分配介绍
  • 方法区
  • 本地方法栈
  • 寄存器

image-20230125113025414

简化格式只是简化了代码书写,真正运行期间还是按照完整格式运行的,int[] arr = new int[]{11,22,33};

5.2 方法的参数传递问题

方法的参数传递问题:

  1. 基本数据类型:传递的是数据值
  2. 引用数据类型:传递的是地址值

问题:Java到底是值传递,还是址传递?

回答:值传递,地址值也是值

代码如下:

package cn.edu.hgu.args;

public class ArgsTest1 {
    public static void main(String[] args) {
        int number = 100;
        System.out.println("调用change方法前:"+number);
        change(number);
        System.out.println("调用change方法后:"+number);

    }
    public static void change(int number){
        number = 200;
    }

}

输出结果为:

调用change方法前:100
调用change方法后:100

修改一下上面的代码:

package cn.edu.hgu.args;

public class ArgsTest1 {
    public static void main(String[] args) {
        int number = 100;
        System.out.println("调用change方法前:"+number);
        number = change(number);
        System.out.println("调用change方法后:"+number);

    }
    public static int change(int number){
        number = 200;
        return number;
    }

}

输出结果为:

调用change方法前:100
调用change方法后:200

下面我们来看一下对数组进行操作:

package cn.edu.hgu.args;

public class ArgsTest1 {
    public static void main(String[] args) {
        int[] arr = {11,22,33,44,55};
        System.out.println("调用change方法前:"+arr[0]);
        change(arr);
        System.out.println("调用change方法后:"+arr[0]);

    }
    public static void change(int[] arr){
        arr[0] = 66;
    }

}

输出结果为:

调用change方法前:11
调用change方法后:66

总结,对于基本数据类型,传递的是数据值,在方法里不能直接修改;对于引用数据类型,传递的是地址值,方法会根据地址值找到数据所在的位置,从而对数据进行修改。

6. 数组常见问题

6.1 索引越界异常

ArrayIndexOutOfBoundsException 当访问了数组中不存在的索引,就会引发索引越界异常

我们通过案例来了解一下:

package cn.edu.hgu.exception;

public class ArrayIndexOutOfBoundsExceptionDemo {
    public static void main(String[] args) {
        int[] arr ={11,22,33};
        System.out.println(arr[10]);
    }
}

输出异常:

image-20230125115300466

就是说,我们的数组长度为3,但使用的索引10超出了范围。

6.2 空指针异常

当引用数据类型变量被赋值为 null 之后,地址的指向被切断,还继续访问堆内存数据,就会引发空指针异常

演示如下:

package cn.edu.hgu.exception;

public class NullPointerExceptionDemo {
    public static void main(String[] args) {
        int[] arr ={11,22,33};

        arr = null;
        System.out.println(arr[0]);
    }
}

输出结果为:

image-20230125130201584

三、二维数组

1. 二维数组介绍

二维数组是一种容器,该容器用于存储一维数组。

如果销售部门要根据季度进行分组,那么一维数组就不太适合了。

image-20230125130239297

使用思路:

今后若要操作的 多组 数据,属于同一组数据就可以考虑使用二维数组行维护

2. 二维数组静态初始化

2.1 二维数组静态初始化格式

格式:

数据类型[][] 数组名 = new 数据类型[][] {{元素1,元素2},{元素1, 元素2}};

范例:

int[][] arr = new int[][]{{11,22},{33,44}};

简化格式:

数据类型[][] 数组名 = {{元素1,元素2}, {元素1, 元素2}};

范例:

int[][] arr = {{11,22},{33,44}};

我们来练习一下吧:

package cn.edu.hgu.array2;

public class ArrayDemo1 {
    public static void main(String[] args) {
        int[][] arr = {
                {11, 22, 33},
                {44, 55, 66}
        };
        System.out.println(arr);//[[I@4eec7777
        System.out.println(arr[0]);//[I@3b07d329
        System.out.println(arr[1]);//[I@41629346
    }
}

细节:二维数组在储存一维数组的时候,具体储存的是一维数组的地址值

2.2 二维数组元素访问

格式:

数组名[m索引][n索引];
  • m索引:指定访问哪一个一维数组
  • n索引:访问一维数组中的哪一个元素

范例:

int[][] arr = new int[][]{{11,22},{33,44}};arr[1][0];

代码实现:

package cn.edu.hgu.array2;

public class ArrayDemo1 {
    public static void main(String[] args) {
        int[][] arr = {
                {11, 22, 33},
                {44, 55, 66}
        };
        System.out.println(arr[1][1]);//55
        System.out.println(arr[0][2]);//33

    }

}

3. 二维数组遍历

使用双重循环来解决问题。

案例:二维数组遍历-打印

需求:已知一个二维数组 arr = { {11 , 22 , 33} , {33 , 44 , 55} }; 遍历该数组,打印元素并求和。

分析:

  1. 遍历二维数组,取出里面每一个一维数组
  2. 在遍历的过程中,对每一个一维数组继续完成遍历,获取内部存储的每一个元素

代码实现:

package cn.edu.hgu.test;

public class ArrayTest8 {
    public static void main(String[] args) {
        int[][] arr = {
                {11, 22, 33},
                {33, 44, 55}
        };
        printArray(arr);
    }

    /**
     * 打印二维数组
     */
    public static void printArray(int[][] arr) {
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[i].length; j++) {
                System.out.println(arr[i][j]);
            }
        }
    }
}

输出结果为:

image-20230125164130195

案例:二维数组遍历-求和

需求:已知一个二维数组 arr = { {11 , 22 , 33} , {33 , 44 , 55} }; 对内部存储的元素累加求和,并将结果输出在控制台

分析:

  1. 定义求和变量
  2. 遍历二维数组,取出里面每一个一维数组
  3. 在遍历的过程中,对每一个一维数组继续完成遍历,获取内部存储的每一个元素
  4. 求和累加
  5. 打印求和结果

我们在上一个案例的基础上进行改造:

package cn.edu.hgu.test;

public class ArrayTest8 {
    public static void main(String[] args) {
        int[][] arr = {
                {11, 22, 33},
                {33, 44, 55}
        };
        printArray(arr);

        int sum = getSum(arr);
        System.out.println("二维数组和为:" + sum);
    }

    /**
     * 打印二维数组
     */
    public static void printArray(int[][] arr) {
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[i].length; j++) {
                System.out.println(arr[i][j]);
            }
        }
    }

    /**
     * 二维数组求和
     */
    public static int getSum(int[][] arr) {
        int sum = 0;
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[i].length; j++) {
                sum += arr[i][j];
            }
        }
        return sum;
    }
}

输出结果为:

image-20230125164655966

4. 二维数组动态初始化

二维数组动态初始化格式:

数据类型[][] 数组名 = new 数据类型[m][n];
  • m表示这个二维数组,可以存放多少个一维数组
  • n表示每一个一维数组,可以存放多少个元素

范例:

int[][] arr = new int[2][3];

该数组可以存放2个一维数组,每个一维数组中可以存放3个int类型元素

是否可以将创建好的一维数组,存入二维数组?可以

package cn.edu.hgu.array2;

public class ArrayDemo2 {
    public static void main(String[] args) {
        // 该数组可以存放2个一维数组,每个一维数组中可以存放3个int类型元素
        int[][] arr = new int[2][3];

        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[i].length; j++) {
                System.out.println(arr[i][j]);
            }
        }

        int[] arr1 = {11,22,33};
        int[] arr2 = {44,55,66};
        arr[0] = arr1;
        arr[1] = arr2;

        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[i].length; j++) {
                System.out.println(arr[i][j]);
            }
        }
    }
}

输出结果为:

image-20230125171010773

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

W_chuanqi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值