一、多维数组简介
1.为什么需要二维数组
我们看下面这个例子?"
某公司2022年全年各个月份的销售额进行登记。按月份存储,可以使用一维数组。如果改写为按季度为单位存储怎么办呢?
或许现在学习了一维数组的你只能申请四个一维数组去存储每个季度的销售额吧?和一一维数组的思想一样,能不能有一个容器将这四个一维数组装起来然后提供一个统一的变量名供我们使用呢?答案是肯定的。我们在学习一维数组的时候也学到,数组的元素可以是基本数据类型也可以是引用数据类型,而数组本身就是引用数据类型。所以可以将数组作为数组的元素,这就是多维数组。
例如:
|-----|-----------------------------------------------------------------------------------------|
| 按月份 | int[] monthData = new int[]{23,43,22,34,55,65,44,67,45,78,67,66}; |
| 按季度 | int[][] quarterData = new int[][]{{23,43,22},{34,55,65},{44,67,45},{78,67,66}}; |
总结:
|--------------------------------------------------------------------------------|
| * 对于二维数组的理解,可以看成是一维数组array1又作为另一个一维数组array2的元素而存在。 * 其实,从数组底层的运行机制来看,其实没有多维数组。 |
二、二维数组的声明与初始化
1.二维数组的声明
|------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 语法格式 | //推荐 元素的数据类型[][] 二维数组的名称; //不推荐(但可行) 元素的数据类型 二维数组名[][]; //不推荐(但可行) 元素的数据类型[] 二维数组名[]; |
| 举例 | public class Test20TwoDimensionalArrayDefine { public static void main(String[] args) { //存储多组成绩 int[][] grades; //存储多组姓名 String[][] names; int[] x, y[];//x是一维数组,y是二维数组 } } |
2.二维数组的静态初始化
|----|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 格式 | int[][] arr = new int[][]{{3,8,2},{2,7},{9,0,1,6}}; |
| 举例 | int[][] arr = {{1,2,3},{4,5,6},{7,8,9,10}};//声明与初始化必须在一句完成(类型推断) int[][] arr = new int[][]{{1,2,3},{4,5,6},{7,8,9,10}}; int[][] arr; arr = new int[][]{{1,2,3},{4,5,6},{7,8,9,10}}; arr = new int[3][3]{{1,2,3},{4,5,6},{7,8,9,10}};//错误,静态初始化右边new 数据类型[][]中不能写数字 注意:二维数组也有length属性。例如:arr.length;与 arr[2].length; |
3.二维数组的动态初始化
a)使用场景
如果二维数组的每一个数据,甚至是每一行的列数,需要后期单独确定,那么就只能使用动态初始化方式了。动态初始化方式分为两种格式。
b)格式一:规则二维表(每一行的列数是相同的)
|----|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 格式 | //(1)确定行数和列数 元素的数据类型[][] 二维数组名 = new 元素的数据类型[m][n]; //其中,m:表示这个二维数组有多少个一维数组。或者说一共二维表有几行 //其中,n:表示每一个一维数组的元素有多少个。或者说每一行共有一个单元格 //此时创建完数组,行数、列数确定,而且元素也都有默认值 //(2)再为元素赋新值 二维数组名[行下标][列下标] = 值; |
| 举例 | int[][] arr = new int[3][2]; * 定义了名称为arr的二维数组 * 二维数组中有3个一维数组 * 每一个一维数组中有2个元素 * 一维数组的名称分别为arr[0], arr[1], arr[2] * 给第一个一维数组1脚标位赋值为78写法是:arr[0][1] = 78;
|
c)格式二:不规则二维表(每一行的列数不一样)
|----|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 格式 | //(1)先确定总行数 元素的数据类型[][] 二维数组名 = new 元素的数据类型[总行数][]; //此时只是确定了总行数,每一行里面现在是null //(2)再确定每一行的列数,创建每一行的一维数组 二维数组名[行下标] = new 元素的数据类型[该行的总列数]; //此时已经new完的行的元素就有默认值了,没有new的行还是null //(3)再为元素赋值 二维数组名[行下标][列下标] = 值; |
| 举例 | int[][] arr = new int[3][]; * 二维数组中有3个一维数组。 * 每个一维数组都是默认初始化值null (注意:区别于格式1) * 可以对这个三个一维数组分别进行初始化:arr[0] = new int[3]; arr[1] = new int[1]; arr[2] = new int[2]; * 注:int[][]arr = new int[][3]; //非法 |
4.数组的长度和角标
|----|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 说明 | * 二维数组的长度/行数:二维数组名.length * 二维数组的某一行:二维数组名[行下标],此时相当于获取其中一组数据。它本质上是一个一维数组。行下标的范围:[0, 二维数组名.length-1]。此时把二维数组看成一维数组的话,元素是行对象。 * 某一行的列数:二维数组名[行下标].length,因为二维数组的每一行是一个一维数组。 * 某一个元素:二维数组名[行下标][列下标],即先确定行/组,再确定列。 |
| 举例 | public class Test22TwoDimensionalArrayUse { public static void main(String[] args){ //存储3个小组的学员的成绩,分开存储,使用二维数组。 /* int[][] scores1; int scores2[][]; int[] scores3[];*/ int[][] scores = { {85,96,85,75}, {99,96,74,72,75}, {52,42,56,75} }; System.out.println(scores);//[[I@15db9742 System.out.println("一共有" + scores.length +"组成绩."); //[[:代表二维数组,I代表元素类型是int System.out.println(scores[0]);//[I@6d06d69c //[:代表一维数组,I代表元素类型是int System.out.println(scores[1]);//[I@7852e922 System.out.println(scores[2]);//[I@4e25154f //System.out.println(scores[3]);//ArrayIndexOutOfBoundsException: 3 System.out.println("第1组有" + scores[0].length +"个学员."); System.out.println("第2组有" + scores[1].length +"个学员."); System.out.println("第3组有" + scores[2].length +"个学员."); System.out.println("第1组的每一个学员成绩如下:"); //第一行的元素 System.out.println(scores[0][0]);//85 System.out.println(scores[0][1]);//96 System.out.println(scores[0][2]);//85 System.out.println(scores[0][3]);//75 //System.out.println(scores[0][4]);//java.lang.ArrayIndexOutOfBoundsException: 4 } } |
三、二维数组的遍历
|----|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 格式 | for(int i=0; i<二维数组名.length; i++){ //二维数组对象.length for(int j=0; j<二维数组名[i].length; j++){//二维数组行对象.length System.out.print(二维数组名[i][j]); } System.out.println(); } |
| 举例 | public class Test23TwoDimensionalArrayIterate { public static void main(String[] args) { //存储3个小组的学员的成绩,分开存储,使用二维数组。 int[][] scores = { {85,96,85,75}, {99,96,74,72,75}, {52,42,56,75} }; System.out.println("一共有" + scores.length +"组成绩."); for (int i = 0; i < scores.length; i++) { System.out.print("第" + (i+1) +"组有" + scores[i].length + "个学员,成绩如下:"); for (int j = 0; j < scores[i].length; j++) { System.out.print(scores[i][j]+"\t"); } System.out.println(); } } } |
四、二维数组的默认值
|----|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 举例 | ①int[][] arr1 = new int[][]; ②int[][] arr2 = new int[2][]; ③int[][] arr3 = new int[3][3]; ...... |
| 说明 | ①写法是错误的,因为在创建二维数组的时候缺少维数,不知道创建多大空间。 ②创建一个有两个元素的二维数组,由于两个元素并未定义,而二维数组是引用数据类型,所以两个元素的默认值均为null。 ③创建一个有三个元素的二维数组,由于三个元素均定义为int类型的一维数组,所以二维数组的三个元素保存的是三个一维数组的地址值。而三个一维数组是int类型一维数组,所以默认值是0。 ...... |
| 总结 | ①byte、short、int的默认值是0 ②long的默认值是0L ③float的默认值是0.0F ④double的默认值是0.0 ⑤char的默认值是0或'\u0000'(表现为空) ⑥boolean的默认值是false ⑦引用类型的默认值是null |
五、内存解析
解析一:
解析二:
六、案例
案例一:获取arr数组中所有元素的和。
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| public class test { public static void main(String[] args) { int[][] arr = new int[][]{{3,5,8},{12,9},{7,0,6,4}}; int sum = 0; for(int i=0;i<arr.length;i++){ for(int j=0;j<arr[i].length;j++){ sum += arr[i][j]; } } System.out.println("总和为:" + sum); } } |
案例二:声明:int[] x,y[]; 在给x,y变量赋值以后,以下选项允许通过编译的是:
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 声明:int[] x,y[]; 在给x,y变量赋值以后,以下选项允许通过编译的是: a) x[0] = y; //no b) y[0] = x; //yes c) y[0][0] = x; //no d) x[0][0] = y; //no e) y[0][0] = x[0]; //yes f) x = y; //no 提示: 一维数组:int[] x 或者int x[] 二维数组:int[][] y 或者 int[] y[] 或者 int y[][] |
案例三:使用二维数组打印一个 10 行杨辉三角。
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| public class YangHuiTest { public static void main(String[] args) { //1. 动态初始化的方式创建二维数组 int[][] yangHui = new int[10][]; for (int i = 0; i < yangHui.length; i++) { yangHui[i] = new int[i + 1]; //2. 给数组元素赋值 // 2.1 给外层数组元素中的首元素和末元素赋值 yangHui[i][0] = yangHui[i][i] = 1; //2.2 给外层数组元素中的非首元素和非末元素赋值(难) //if(i > 1){ //从 i == 2 开始执行 for(int j = 1;j < yangHui[i].length - 1;j++){ //非首元素和非末元素的角标范围 yangHui[i][j] = yangHui[i-1][j-1] + yangHui[i-1][j]; } //} } //3. 遍历二维数组 for (int i = 0; i < yangHui.length; i++) { for (int j = 0; j < yangHui[i].length; j++) { System.out.print(yangHui[i][j] + "\t"); } System.out.println(); } } } |