JavaSE&数组(上):https://developer.aliyun.com/article/1491513
演示完毕之后,回到资料我们总结一下数组初始化的两种方式的各自使用场景:
- 静态初始化: 开始就存入元素值,适合一开始就能确定元素值的业务场景
- 动态初始化: 指定数组长度,后期赋值,适合开始知道数据的数量,但是不确定具体元素值的业务场景
- 注意: 两种初始化的方式是独立的,不可以混用
好了,关于数组初始化之动态初始化我们就先讲到这里。
1.8 案例4(数组元来自键盘录入)
来,继续啊,下面我们来做一个案例:数组元素来自键盘录入
首先呢,我们来看一下具体的需求:
需求: 定义一个可以存储5个元素的int数组,数据来自于键盘录入,最后遍历数组,把元素输出在控制台
首先,我们来简单的分析一下:
这个数组可以存储5个 int 类型的元素,但是数据来自于键盘录入,也就是先指定数组长度,后期赋值。
这很明显适合使用数组的动态初始化,所以,这里我们将采用动态初始化对数组进行初始化。
接着,数据来自于键盘录入,我们得知道这里要使用Scanner来实现。
明确了这两个内容后,下面我们到 IDEA 中一起去实现一下:
import java.util.Scanner; /* 需求:定义一个可以存储5个元素的int数组,数据来自于键盘录入,最后遍历数组,把元素输出在控制台 */ public class ArrayTest { public static void main(String[] args) { //定义一个数组,并进行动态初始化 int[] arr = new int[5]; //创建键盘录入对象 Scanner sc = new Scanner(System.in); // //录入第1个数据 // System.out.println("请输入第1个数据:"); int i = sc.nextInt(); arr[0] = i; // arr[0] = sc.nextInt(); // // //录入第2个数据 // System.out.println("请输入第2个数据:"); // arr[1] = sc.nextInt(); for (int i = 0; i < arr.length; i++) { System.out.println("请输入第" + (i + 1) + "个元素:"); arr[i] = sc.nextInt(); } printArray(arr); //输出内容并换行 // System.out.println("hello"); // System.out.println("world"); //输出内容不换行 // System.out.print("hello"); // System.out.print("world"); } public static void printArray(int[] arr) { System.out.print("["); for (int i = 0; i < arr.length; i++) { if(i==arr.length-1) { System.out.print(arr[i]); }else { System.out.print(arr[i] + ", "); } } System.out.println("]"); } /* 参数:int[] arr 返回值:void */ // public static void printArray(int[] arr) { // for (int i = 0; i < arr.length; i++) { // System.out.println(arr[i]); // } // } }
在讲解过程中,我们讲到了一个新的输出语句,不带ln的方法,它只输出内容,不换行。
而以前我们使用的输出语句,不仅仅把内容输出,而且在输出内容后,会加一个换行。
好了,关于案例数组元素来自键盘录入我们就先讲到这里。
1.9 数组内存图
下面我们来学习数组内存图。
这里呢,我们通过单个数组的内存图让大家了解一下数组在内存中的存储和使用就可以了。
整个过程讲解的是下图代码的执行流程,大家能够听懂即可。
最后,我们自己编写代码验证一下:
/* 数组内存图代码 */ public class ArrayTest01 { public static void main(String[] args) { int[] arr = new int[3]; //输出数组名及元素 System.out.println(arr); System.out.println(arr[0]); System.out.println(arr[1]); System.out.println(arr[2]); //给数组中的元素赋值 arr[0] = 100; arr[2] = 200; //再次输出数组名及元素 System.out.println(arr); System.out.println(arr[0]); System.out.println(arr[1]); System.out.println(arr[2]); } }
由于仅仅是验证讲解的结论,故不需要练习。
1.10 数组使用中的两个小问题
下面我们来讲解一下数组使用中的两个小问题。
先来看第一个问题:请问下列代码有问题吗?如果有,是什么问题?如何解决?
int[] arr = new int[3]; // 输出元素 System.out.println(arr[3]);
通过内存图进行讲解:
最终结论是:
- 有问题
- 访问了不存在的索引位置元素
- 修改不存在的索引为正确的索引。范围(0~数组长度-1)
再来看第二个问题:请问下列代码有问题吗?如果有,是什么问题?如何解决?
int[] arr = new int[3]; System.out.println(arr[2]); // 赋值为null arr = null; // 输出元素 System.out.println(arr[0]);
通过内存图进行讲解:
最终结论是:
- 有问题
- 对象设置为null,不在指向堆内存数据了,还想继续访问堆内存数据
- 对象在使用前,进行不为null的判断
讲解完毕后,到IDEA中再去通过代码验证一下:
/* 数组使用中的两个小问题 1:索引越界:访问了数组中不存在的索引对应的元素,造成索引越界问题 ArrayIndexOutOfBoundsException 2:空指针异常:对象不再指向堆内存,还想继续访问数据,访问失败 NullPointerException null:空值,引用数据类型的默认值,表示不指向任何有效对象 */ public class ArrayTest02 { public static void main(String[] args) { int[] arr = new int[3]; //输出元素 //Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3 // System.out.println(arr[3]); System.out.println(arr[2]); //把null赋值给arr arr = null; //输出元素 //Exception in thread "main" java.lang.NullPointerException: Cannot load from int array because "arr" is null if(arr != null) { System.out.println(arr[0]); } } }
由于仅仅是验证讲解的结论,故不需要练习。
2:二维数组
2.1 二维数组概述和课程安排
下面我们来学习二维数组。前面我们讲解的数组,一般称之为一维数组。
为了帮助大家理解二维数组呢?这里我们来看这样的一个场景:
需求:我们要存储多个班级的学生的考试成绩,该怎么办呢?
如果要存储一个班级中多个学生的考试成绩,我们就可以采用数组来存储。
现在的问题是?多个班级的考试成绩,我们针对每个班级都采用数组存储。
第一个班级:数组1
第二个班级:数组2
第三个班级:数组3
…
但是多个班级,也可以采用数组存储啊。所以,Java就提供了二维数组供我们使用。
这里我们给二维数组一个简单的定义:
二维数组: 元素为一维数组的数组
知道了什么是二维数组后,我们再说一下二维数组的定义格式:
它有这样的三个格式,用[][]表示二维数组:
数据类型[] [] 变量名; int[] [] arr; 推荐
数据类型 变量名[] []; int arr[] [];
数据类型[] 变量名[]; int[] arr[];
推荐使用第一种格式。
首先,我们讲解二维数组初始化,这样我们就能够给二维数组中的元素赋值了。
接着,我们讲解二维数组元素访问,这样我们就能够获取到二维数组中的数据了。
然后,我们讲解二维数组内存图,这样我们就能够对二维数组在内存中的存储和操作做到知其然也知其所以然。
最后,我们讲解二维数组常见操作,这样我们就能够应用二维数组解决常见的问题了。
好了,到此关于二维数组的概述和课程安排我们就先讲到这里。
2.2 二维数组初始化
来,继续啊,下面我们来学习二维数组初始化,和一维数组一样,二维数组初始化也有两种格式:
静态初始化
动态初始化
首先来看静态初始化:
格式: 数据类型[] [] 变量名 = new 数据类型[] []{{元素…},{元素…},{元素…},…};
范例: int[] [] arr = new int[] []{{1,2,3},{4,5,6},{7,8,9}};
解读:
定义了一个二维数组
二维数组中有三个元素(一维数组)
每一个一维数组有三个元素(int类型数据)
注意:一维数组中元素的个位可以是不同的
比如: int[] [] arr = new int[] []{{1,2,3},{4,5},{6,7,8,9}};
同样,针对静态初始化,二维数组也给出了简化格式:
**简化格式:**数据类型[][] 变量名 = {{元素…},{元素…},{元素…},…};
**范例:**int[] [] arr = {{1,2,3},{4,5,6},{7,8,9}};
再来看动态初始化:
**格式:**数据类型[] [] 变量名 = new 数据类型[m] [n];
**范例:**int[] [] arr = new int[2] [3];
解读:
定义了一个二维数组
二维数组中有2个元素(一维数组)
每一个一维数组有3个元素(int类型数据)
他们的各自使用场景和一维数组中讲解的是一样的:
静态初始化:适合一开始就能确定元素值的业务场景
动态初始化:适合开始知道数据的数量,但是不确定具体元素值的业务场景
好了,关于二维数组的初始化我们就先讲到这里
2.3 二维数组元素访问
来,继续啊,下面我们来学习二维数组元素访问。
关于二维数组的元素访问,我们先到idea中去讲解,然后再回来总结:
/* 静态初始化简化格式:数据类型[][] 数组名 = {{元素...},{元素...},{元素...},...}; */ public class ArrayDemo { public static void main(String[] args) { //静态初始化简化格式:数据类型[][] 数组名 = {{元素...},{元素...},{元素...},...}; int[][] arr = {{1, 2, 3}, {4, 5, 6}}; //输出数组名 System.out.println(arr); //[[I@776ec8df System.out.println(arr[0]); //[I@4eec7777 System.out.println(arr[1]); //[I@3b07d329 //如何获取到数据1,2,3呢? System.out.println(arr[0][0]); System.out.println(arr[0][1]); System.out.println(arr[0][2]); } }
讲解完毕后,回到资料总结一下:
- 获取二维数组:数组名
- 获取每一个一维数组:数组名[索引]
- 获取每一个二维数组元素:数组名[索引] [索引]
好了,关于二维数组的元素访问我们就先讲到这里。
2.4 二维数组内存图
来,继续啊,下面我们来学习二维数组的内存图。
这里呢,我们通过内存图的方式让大家了解一下二维数组在内存中的存储和使用就可以了。
整个过程讲解的是下图代码的执行流程,大家能够听懂即可。
最后,我们自己编写代码验证一下:
/* 二维数组内存图代码 */ public class ArrayTest { public static void main(String[] args) { //定义二维数组 int[][] arr = {{1, 2, 3}, {4, 5, 6}}; //输出数组中的元素 System.out.println(arr[0][1]); System.out.println(arr[1][1]); //修改数组中的元素 arr[0][1] = 10; arr[1][1] = 20; //再次输出数组中的元素 System.out.println(arr[0][1]); System.out.println(arr[1][1]); } }
由于仅仅是验证讲解的结论,故不需要练习。
2.5 案例5(二维数组常见操作之遍历)
来,继续啊,下面我们来学习二维数组常见操作:
这里我们讲解两个操作:
- 遍历
- 元素打乱
首先,我们来看二维数组遍历。
这里有一个需求:已知一个二维数组 arr = {{1,2,3},{4,5,6},{7,8,9}}; 请把元素在控制台输出。
看完需求之后,我们到IDEA中一起去实现一下,然后再回来总结:
/* 需求:已知一个二维数组 arr = {{1,2,3},{4,5,6},{7,8,9}}; 请把元素在控制台输出 */ public class ArrayTest01 { public static void main(String[] args) { //定义二维数组,并进行静态初始化 int[][] arr = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; //获取数据1,2,3 // System.out.println(arr[0][0]); // System.out.println(arr[0][1]); // System.out.println(arr[0][2]); // for (int i = 0; i < arr[0].length; i++) { // System.out.println(arr[0][i]); // } // // //获取数据4,5,6 System.out.println(arr[1][0]); System.out.println(arr[1][1]); System.out.println(arr[1][2]); // for (int i = 0; i < arr[1].length; i++) { // System.out.println(arr[1][i]); // } // // //获取数据7,8,9 System.out.println(arr[2][0]); System.out.println(arr[2][1]); System.out.println(arr[2][2]); // for (int i = 0; i < arr[2].length; i++) { // System.out.println(arr[2][i]); // } for (int i = 0; i < arr.length; i++) { //arr[i] for (int j = 0; j < arr[i].length; j++) { System.out.print(arr[i][j]+" "); } System.out.println(); } } }
在代码讲解过程中,我们讲解了循环嵌套:for循环的语句体是循环语句,这种现象被称为循环嵌套。
讲解完毕后,回到资料中我们去总结一下:
在实现的过程中,我们在二维数组中使用了循环嵌套:
① 循环嵌套:循环语句中嵌套循环语句
② 通过外层循环可以得到一维数组
③ 在通过内存循环可以得到每一个二维数组元素
好了,关于二维数组常见操作之遍历我们就先讲到这里。
讲解完毕后,大家赶快动手练习一下吧。
2.6 案例6(二维数组常见操作之元素打乱)
来,继续啊,下面我们来学习二维数组中元素打乱。
在前面呢,我们讲解过一维数组中的元素打乱,这里的思路和前面是一样的,也是要随机产生二维数组中元素的索引,并进行元素交换。
只不过呢,二维数组元素的索引是两个值,所以,这里要产生两个随机数。
知道了二维数组元素打乱的基本思路后,下面我们到IDEA中去实现一下:
import java.util.Random; /* 需求:已知二维数组 arr = {{1,2,3},{4,5,6},{7,8,9}};用程序实现把数组中的元素打乱,并在控制台输出打乱后的数组元素 */ public class ArrayTest02 { public static void main(String[] args) { //定义二维数组,并进行静态初始化 int[][] arr = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; //创建随机数对象 Random r = new Random(); //遍历二维数组,进行元素打乱 for (int i = 0; i < arr.length; i++) { for (int j = 0; j < arr[i].length; j++) { //arr[i][j] int x = r.nextInt(arr.length); int y = r.nextInt(arr[x].length); //元素交换 int temp = arr[i][j]; arr[i][j] = arr[x][y]; arr[x][y] = temp; } } for (int i = 0; i < arr.length; i++) { for (int j = 0; j < arr[i].length; j++) { System.out.print(arr[i][j] + " "); } System.out.println(); } } }
好了,关于二维数组常见操作之元素打乱我们就先讲到这里