【Java学习笔记之八】java二维数组及其多维数组的内存应用拓展延伸

时间:2022-04-05 08:05:43
多维数组声明
数据类型[][] 数组名称;
数据类型[] 数组名称[];
数据类型数组名称[][];
以上三种语法在声明二维数组时的功能是等价的。同理,声明三维数组时需要三对中括号,中括号的位置可以在数据类型的后面,也可以在数组名称的后面,其它的依次类推。
例如:
int[][] map;
char c[][];
和一维数组一样,数组声明以后在内存中没有分配具体的存储空间,也没有设定数组的长度。 
-----------------------------------------------------------------------------------------------------------------------------------------------------------
多维数组初始化
和一维数组一样,多维数组的初始化也可以分为静态初始化(整体赋值)和动态初始化两种,其语法格式如下。 
静态初始化
以二维数组的静态初始化为例,来说明多维数组静态初始化的语法格式。
示例代码如下:
int[][] m = {{1,2,3},{2,3,4}};
在二维数组静态初始化时,也必须和数组的声明写在一起。数值书写时,使用两个大括号嵌套实现,在最里层的大括号内部书写数字的值。数值和数值之间使用逗号分隔,内部的大括号之间也使用逗号分隔。由该语法可以看出,内部的大括号其实就是一个一维数组的静态初始化,二维数组只是把多个一维数组的静态初始化组合起来。
同理,三维数组的静态初始化语法格式如下:
int[][][] b = {{{1,2,3},{1,2,3}},{{3,4,1},{2,3,4}}};
说明:这里只是演示语法格式,数值本身没有意义。
动态初始化
二维数组动态初始化的语法格式:
数据类型[][] 数组名称= new 数据类型[第一维的长度][第二维的长度];
数据类型[][] 数组名称;
数组名称= new 数据类型[第一维的长度][第二维的长度];
示例代码:
byte[][] b = new byte[2][3];
int m[][];
m = new int[4][4];
和一维数组一样,动态初始化可以和数组的声明分开,动态初始化只指定数组的长度,数组中每个元素的初始化是数组声明时数据类型的默认值。例如上面初始化了长度为2X3
的数组b,和4X4 的数组m。使用这种方法,初始化出的第二维的长度都是相同的,如果需要初始化第二维长度不一样的二维数组,则可以使用如下的格式:
int n[][];
n = new int[2][]; //只初始化第一维的长度
//分别初始化后续的元素
n[0] = new int[4];
n[1] = new int[3];
这里的语法就体现了数组的数组概念,在初始化第一维的长度时,其实就是把数组n 看成了一个一维数组,初始化其长度为2,则数组n
中包含的2个元素分别是n[0]和n[1],而这两个元素分别是一个一维数组。后面使用一维数组动态初始化的语法分别初始化n[0]和n[1]。
----------------------------------------------------------------------------------------------------------------------------------------------------------------
引用数组元素
对于二维数组来说,由于其有两个下标,所以引用数组元素值的格式为:
数组名称[第一维下标][第二维下标]
该表达式的类型和声明数组时的数据类型相同。例如引用二维数组m中的元素时,使用m[0][0]引用数组中第一维下标是0,第二维下标也是0 的元素。这里第一维下标的区间是0 到第一维的长度减1,第二维下标的区间是0 到第二维的长度减1。
---------------------------------------------------------------------------------------------------------------------------------------------------------------
获得数组长度
对于多维数组来说,也可以获得数组的长度。但是使用数组名.length获得的是数组第一维的长度。如果需要获得二维数组中总的元素个数,可以使用如下代码:
int[][] m = {{1,2,3,1},{1,3},{3,4,2}};
int sum = 0;
for(int i = 0;i < m.length;i++){         //循环第一维下标
        sum += m[i].length;                 //第二维的长度相加
}
在该代码中,m.length 代表m 数组第一维的长度,内部的m[i]指每个一维数组元素,m[i].length 是m[i]数组的长度,把这些长度相加就是数组m中总的元素个数。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
多维数组使用示例
多维数组在实际使用时,更多的在于数组的设计,在实际使用中,一般对于多维数组的统计相对来说比一维数组要少一些,更多的设计数组的大小,并规定数组中存储值的含义,在代码中按照值的规定使用数组。
所以在实际使用多维数组以前,需要考虑清楚:
① 需要几维数组
② 每一维的长度是多少
③ 按照怎样的规则存储值
④ 数组值的意义是什么
拉丁方阵
要求:实现任意阶拉丁矩阵的存储和输出拉丁矩阵是一种规则的数值序列,例如4 阶的拉丁矩阵如下所示:
1 2 3 4
2 3 4 1
3 4 1 2
4 1 2 3
该矩阵中的数字很规则,在实际解决该问题时,只需要把数值的规律描述出来即可。
实现思路:声明一个变量n,代表矩阵的阶,声明和初始化一个nXn 的数组,根据数据的规律,则对应的数值为(行号+ 列号+ 1),当数值比n 大时,取和n的余数。
实现的代码如下:
int n = 6;
int[][] arr = new int[n][n];
int data; //数值
//循环赋值
for(int row = 0;row < arr.length;row++){
        for(int col = 0;col <arr[row].length;col++){
                data = row + col + 1;
                if(data <= n){
                arr[row][col] = data;
                }else{
                arr[row][col] = data %n;
                }
        }
}
//输出数组的值
for(int row = 0;row < arr.length;row++){
        for(int col = 0;col <arr[row].length;col++){
                System.out.print(arr[row][col]);
                System.out.print(' ');
        }
        System.out.println();
}
该代码中变量data 存储行号+列号+1 的值,每次在赋值时判别data的值是否小于等于n,根据判断的结果赋值对应数组元素的值。
在解决实际问题时,观察数字规律,并且把该规律使用程序进行表达,也是每个程序员需要的基本技能。
----------------------------------------------------------------------------------------------------------------------------------------------------------------- 
杨辉三角
要求:实现10 行杨辉三角元素的存储以及输出。杨辉三角是数学上的一个数字序列,该数字序列如下:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
该数字序列的规律为,数组中第一列的数字值都是1,后续每个元素的值等于该行上一行对应元素和上一行对应前一个元素的值之和。例如第五行第二列的数字4 的值,等于上一行对应元素3 和3 前面元素1 的和。
实现思路:杨辉三角第几行有几个数字,使用行号控制循环次数,内部的数值第一行赋值为1,其它的数值依据规则计算。假设需要计算的数组元素下标为(row,col),则上一个元素的下标为(row – 1,col),前一个元素的下标是(row – 1,col – 1)。
实现代码如下:
int[][] arr = new int[10][10];
//循环赋值
for(int row = 0;row < arr.length;row++){
        for(int col = 0;col <= row;col++){
                if(col == 0){ //第一列
                        arr[row][col] = 1;
                }else{
                        arr[row][col] =arr[row - 1][col] + arr[row - 1][col - 1];
                }
        }
}
//输出数组的值
for(int row = 0;row < arr.length;row++){
        for(int col = 0;col <= row;col++){
                System.out.print(arr[row][col]);
                System.out.print(' ');
        }
        System.out.println();
}
该题目中数字之间的规律比较简单,主要是理解数组的下标基本的处理,加深对于数组下标的认识,控制好数组元素的值。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
存储图形结构
要求:根据数组中的值,在对应位置绘制指定的字符。规定0 绘制空格,1 绘制星号(*)。数组的值如下所示:
{
{0,0,0,1,0,0,0},
{0,0,1,0,1,0,0},
{0,1,0,0,0,1,0},
{1,0,0,0,0,0,1},
{0,1,0,0,0,1,0},
{0,0,1,0,1,0,0},
{0,0,0,1,0,0,0}
}
该题目是一个基本的数组应用,数组中的值存储的是控制信息,程序根据数组中的值实现规定的功能。
实现思路:循环数组中的元素,判断数组中的值,根据值绘制对应的字符即可。
实现的代码如下所示:
int[][] map = {
{0,0,0,1,0,0,0},
{0,0,1,0,1,0,0},
{0,1,0,0,0,1,0},
{1,0,0,0,0,0,1},
{0,1,0,0,0,1,0},
{0,0,1,0,1,0,0},
{0,0,0,1,0,0,0}
};
//输出数组的值
for(int row = 0;row < map.length;row++){
        for(int col = 0;col <map[row].length;col++){
                switch(map[row][col]){
                    case 0:
                        System.out.print(' ');
                        break;
                    case 1:
                        System.out.print('*');
                        break;
        }
}
        System.out.println();
}
类似的代码在游戏开发中,可以用来代表游戏中的地图数据,或者俄罗斯方块等益智游戏中地图块的值。
------------------------------------------------------------------------------------------------------------------------------------------------------------------
螺旋数组
要求:存储和输出nXm 的螺旋数组,其中n 和m 为大于0 的整数。以下是一些螺旋数组的示例:
1    2    3    4         1     2     3     4     5
12  13 14   5         14   15  16    17   6
11  16  15  6         13   20  19    18   7
10   9    8   7         12   11  10     9    8
4X4 螺旋数组4X5 螺旋数组对于螺旋数组来说,其中的数值很有规则,就是按照旋转的结构数值每次加1,实现该功能需要对数组和流程控制有角深刻的认识。
实现思路:声明一个变量来代表需要为数组元素赋的值,对于其中的数字来说,每个数字都有一个移动方向,这个方向指向下一个元素,根据该方向改变数组的下标,如果到达边界或指向的元素已经赋值,则改变方向。
实现代码如下:
int n = 4;
int m = 5;
int[][] data = new int[n][m];
int dire; //当前数字的移动方向
final int UP = 0;             //上
final int DOWN = 1;         //下
final int LEFT = 2;         //左
final int RIGHT = 3;        //右
dire = RIGHT;
int value = 1;             //数组元素的值
int row = 0;                 //第一维下标
int col = 0;                 //第二维下标
data[0][0] = 1;         //初始化第一个元素
while(value < n * m){
        switch(dire){
        case UP:
                row--; //移动到上一行
                if(row < 0){ //超过边界
                        row++; //后退
                        dire = RIGHT;
                        continue; //跳过该次循环
                }else if(data[row][col] != 0){//已赋值
                        row++; //后退
                        dire = RIGHT;
                        continue; //跳过该次循环
                }
                break;
        case DOWN:
                row++; //移动到下一行
                if(row >= n){ //超过边界
                        row--; //后退
                        dire = LEFT;
                        continue; //跳过该次循环
                }else if(data[row][col] != 0){//已赋值
                        row--; //后退
                        dire = LEFT;
                        continue; //跳过该次循环
                }
                break;
        case LEFT:
                col--; //移动到前一列
                if(col < 0){ //超过边界
                        col++; //后退
                        dire = UP;
                        continue; //跳过该次循环
                }else if(data[row][col] != 0){//已赋值
                        col++; //后退
                        dire = UP;
                        continue; //跳过该次循环
                }
                break;
        case RIGHT:
                col++; //移动到后一行
                if(col >= m){ //超过边界
                        col--; //后退
                        dire = DOWN;
                        continue; //跳过该次循环
                }else if(data[row][col] != 0){//已赋值
                        col--; //后退
                        dire = DOWN;
                        continue; //跳过该次循环
                }
                break;
        }
        value++; //数值增加1
        data[row][col] = value;//赋值
}
//输出数组中的元素
for(int i = 0;i < data.length;i++){
        for(int j = 0;j < data[i].length;j++){
                if(data[i][j] < 10){//右对齐
                        System.out.print(' ');
                }
                System.out.print(data[i][j]);
                System.out.print(' ');
        }
        System.out.println();
}
在该代码中dire
代表当前元素的移动方向,每个根据该变量的值实现移动,如果移动时超出边界或移动到的位置已赋值,则改变方向,并跳过本次循环,如果移动成功,则数值增加1,对数组元素进行赋值。对于多维数组来说,更多的是设计数组的结构,并根据逻辑的需要变换数组的下标,实现对于多维数组元素的操作。

二维数组内存结构

【Java学习笔记之八】java二维数组及其多维数组的内存应用拓展延伸

不规则二维数组

 //1.二维数组的定义
//2.二维数组的内存空间
//3.不规则数组
package me.array;
public class Array2Demo{ public static void main(String[] args){ //创建和打印不规则二维数组
int arr[ ][ ]; arr=new int[3][];//现在说明为不规则数组 arr[0]=new int[10];//arr[0]指向另一个一位数组
arr[1]=new int[3];
arr[2]=new int[4]; //赋值
for(int i=0;i<arr.length;i++){ for(int j=0;j<arr[i].length;j++){ arr[i][j]=j;
} } //输出
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();
} /*输出结果:
0 1 2 3 4 5 6 7 8 9
0 1 2
0 1 2 3
*/// } }
 //3.编写一个方法,返回double型二维数组,数组通过解析字符串参数获得。
//如"1,2;3,4,5;6,7,8"
//d[0,0]=1.0 d[0,1]=2.0 d[1,0]=3.0 ....
package me.parser;
public class TestString{ public static void main(String[] args){ //1.用字符串分解split(";")成三个字符串数组
//2.再分解split(",") //声明一个二维数组用来装分解好的字符 String s="1,2;3,4,5;6,7,8";
//以split()方法 分解
String[] sFirst=s.split(";"); String[][] word=new String[sFirst.length][]; int flag=0;
for(int i=0;i<sFirst.length;i++){ //打印出已经分开的
//System.out.println(sFirst[i]);
/*这条语句输出
1,2
3,4,5
6,7,8
*///接下来在按照 ,分开他们放入一个一维数组 String[] sSecond=sFirst[i].split(",");
//~ System.out.println(sSecond.length);
//~ /*输出:
//~ 2
//~ ---------------------------------
//~ 3
//~ ---------------------------------
//~ 3
//~ ---------------------------------
//~ *///说明每次sSencond这个一维数组的长度不同
word[i]=new String[sSecond.length];//这步确定行不规则数组的每行长度 //为这个数组赋值
for(int j=0;j<sSecond.length;j++){ word[i][j]=sSecond[j];
} System.out.println("---------------这是第"+(i+1)+"次循环-------------------");
} //输出二维数组
System.out.println("输出二维数组-------------------");
for(int i=0;i<word.length;i++){
for(int j=0;j<word[i].length;j++){ System.out.print(word[i][j]+" ");
}
System.out.println();
}
/*结果:
---------------这是第1次循环-------------------
---------------这是第2次循环-------------------
---------------这是第3次循环-------------------
输出二维数组-------------------
1 2
3 4 5
6 7 8
输出二维数组-------------------
*///
}
}