
5.4 多维数组
虽然一维数组可以处理一般简单的数据,但是在实际的应用中仍显不足,所以Java语言提供了多维数组,但在Java语言中并没有真正的多维数组。所谓多维数组,就是数组元素也是数组的数组。
5.4.1 二维数组
二维数组的声明方式与一维数组类似,内存的分配也一样是用new运算符。其声明与分配内存的格式如下所示:
数据类型[][]数组名; 数组名=new数据类型[行数][列数];
二维数组在分配内存时,要告诉编译器二维数组行与列的个数。因此在上面格式中,“行数”是告诉编译器所声明的数组有多少行,“列数”则是声明每行中有多少列。例如:
int[][]a; //声明二维整型数组a a=new int[3][4]; //分配一块内存空间,供3行4列的整型数组a使用
同样地,也可以用较为简洁的方式来声明数组,其格式如下:
数据类型[][]数组名=new数据类型[行数][列数];
以该种方式声明的数组,在声明的同时,就分配一块内存空间,供该数组使用。如
int[][]a=new int[3][4];
虽然在应用上很像C语言中的多维数组,但还是有区别的,在C语言中定义一个二维数组,必须是一个m×n的矩形,如图5.4所示。Java语言的二维数组不一定是规则的矩形,如图5.5所示。

图5.4 C语言中二维数组必须是矩形

图5.5 Java语言中的二维数组不一定是矩形
如,定义一个如下的数组:
int[][]x=nex int[];
它表示定义了一个数组引用变量x,第一个元素为x[0],第n个元素变量为x[n—1]。x中从x[0]到x[n—1]的每个元素变量正好又是一个整数类型的数组引用变量。需要注意的是,这里只是要求每个元素都是一个数组引用变量,并没有要求它们所引用数组的长度是多少,也就是每个引用数组的长度可以不一样。例如:
int[][]x; x=new int[3][];
这两行代码表示数组x有三个元素,每个元素都是int[]类型的一维数组。该语句相当于定义了三个数组引用变量,分别是int[]x[0],int[]x[1]和int[]x[2],完全可以把x[0]、x[1]和x[2]当成普通变量名来理解。
由于x[0]、x[1]和x[2]都是数组引用变量,因此,必须对它们赋值,指向真正的数组对象,才可以引用这些数组中的元素。例如:
x[0]=new int[3]; x[1]=new int[2];
由此可以看出,x[0]和x[1]的长度可以是不一样的,数组对象中也可以只有一个元素。程序运行到这之后的内存分配情况如图5.6所示。

图5.6 Java中的二维数组可以看成是多个一维数组
x[0]中的第二个元素用x[0][1]来表示,如果要将整数100赋给x[0]中的第二个元素,写法如下:
x[0][1]=100;
如果数组对象正好是一个m×n形式的规则矩阵,可不必向上面代码一样,先创建高维的数组对象后,再逐一创建低维的数组对象。完全可以用一条语句在创建高维数组对象的同时,创建所有的低维数组对象。例如:
int[][]x=new int[2][3];
该语句表示创建了一个2×3形式的二维数组,其内存布局如图5.7所示。

图5.7 规则的二维数组内存分配
在二维数组中,若要取得二维数组的行数,只要在数组名后加上.length属性即可;若要取得数组中某行元素的个数,则须在数组名后加上该行的下标,再加上.length。例如:
x.length; //计算数组x的行数 x[0].length; //计算数组x的第1行元素的个数 x[2].length; //计算数组x的第3行元素的个数
注意:与一维数组相同,用new运算符来为数组申请内存空间时,很容易在数组各维数的指定中出现错误,二维数组要求必须指定高层维数。例如,下面是正确的申请方式:

下面是错误的申请方式:

如果想直接在声明二维数组时就给数组赋初值,可以利用花括号实现,只要在数组的声明格式后面再加上初值的赋值即可。其格式如下:

同样需要注意的是,用户并不需要定义数组的长度,因此在数据类型后面的方括号里并不必填写任何的内容。此外,在花括号内还有几组花括号,每组花括号内的初值会依次赋值给数组的第1,2,…,n+1行元素。例如:

该语句中声明了一个整型数组a,该数组有2行4列共8个元素,花括号里的两组初值会分别依次指定给各行里的元素存放,a[0][0]为11,a[0][1]为22,…,a[1][3]为99。
注意:与一维数组一样,在声明多维数组并初始化时不能指定其长度,否则出错。如“int[2][3]b={{1,2,3},{4,5,6}};”语句在编译时将出错。
【例5.4】 计算并输出杨辉三角形。

该程序的运行结果为:

该程序的第8行声明了一个7行的二维数组iaYong,每行的列数由第10、11行的for循环来定义;第13~19行的for循环用于计算杨辉三角形并存入数组iaYong的相应元素中,其中的第15、18行分别是将第i行的第一个元素和最后一个元素置1;第16行定义的内层for循环用于计算第i行的其他元素,其计算方法是第17行的循环体;第20~25行利用foreach循环将杨辉三角形输出。
5.4.2 三维以上的多维数组
通过对二维数组的介绍,不难发现,要想提高数组的维数,只要在声明数组的时候将下标与中括号再加一组即可,所以三维数组的声明为“int[][][]a;”,而四维数组为“int[][][][]a;”,依次类推。
使用多维数组时,输入输出的方式和一、二维数组相同,但是每多一维,嵌套循环的层数就必须多一层,所以维数越高的数组其复杂度也就越高。
【例5.5】 声明三维数组并赋初值,然后输出该数组的各元素,并计算各元素之和。

程序运行时的结果如下:
a[0][0][0]=1 a[0][0][1]=2 a[0][1][0]=3 a[0][1][1]=4 a[1][0][0]=5 a[1][0][1]=6 a[1][1][0]=7 a[1][1][1]=8 sum=36
该程序利用三层循环来输出三维数组的各元素并计算各元素之和。