欢迎光临
我们一直在努力

7. Java 二维数组

定义

Java 的二维数组本质是数组的数组:外层数组的每个元素是一个一维数组的引用。

一维数组: [1, 2, 3]
二维数组: [[1, 2, 3], [4, 5, 6]] // 2行×3列

与 C 语言连续内存模型不同,Java 的二维数组各内层数组在堆中独立分配,因此天然支持不规则数组(每行列数可不同)。


三种定义方式

方式一:静态初始化

已知全部元素时使用:

String[][] scores = {
{"张三", "90", "85"},
{"李四", "88", "92"}
};

int[][] matrix = {
{1, 2, 3},
{4, 5, 6}
};

方式二:动态初始化

先分配内存再逐个赋值:

int[][] arr = new int[3][2]; // 3行2列,元素默认值 0

arr[0][0] = 10;
arr[0][1] = 20;
arr[1][0] = 30;

方式三:不规则数组

只指定行数,每行列数单独定义:

int[][] jagged = new int[2][];
jagged[0] = new int[2]; // 第0行:2列
jagged[1] = new int[3]; // 第1行:3列

jagged[0][0] = 1;
jagged[1][2] = 9;

静态初始化也可定义不规则数组:

int[][] jagged = {
{1, 2},
{3, 4, 5},
{6}
};


访问与修改

通过 数组名[行索引][列索引] 定位元素,索引从 0 开始:

String[][] scores = {
{"张三", "90", "85"},
{"李四", "88", "92"}
};

String math = scores[0][2]; // 取值:"85"
scores[1][1] = "95"; // 赋值

获取行列数:

int rows = scores.length; // 行数:2
int cols = scores[0].length; // 第0行列数:3

不规则数组中每行列数可能不同,取列数必须用 arr[i].length 而非 arr[0].length。


遍历方式

普通 for 循环

需要索引或修改元素时使用:

int[][] matrix = {
{1, 2, 3},
{4, 5, 6}
};

for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
System.out.print(matrix[i][j] + " ");
}
System.out.println();
}
// 输出:
// 1 2 3
// 4 5 6

增强 for 循环

只读取元素时使用:

for (int[] row : matrix) {
for (int num : row) {
System.out.print(num + " ");
}
System.out.println();
}

Stream 流式遍历(JDK 8+)

import java.util.Arrays;

Arrays.stream(matrix)
.forEach(row -> {
Arrays.stream(row)
.forEach(num -> System.out.print(num + " "));
System.out.println();
});

遍历方式对比

遍历方式

优点

缺点

适用场景

普通 for

有索引,可修改元素

代码较长

需要定位或修改元素

增强 for

代码简洁

无索引,不可修改

仅读取元素

Stream

函数式,可链式过滤映射

JDK 8+ 支持

需要数据过滤转换


不规则数组遍历

内层循环上限必须用当前行的 length:

int[][] jagged = {
{1, 2},
{3, 4, 5}
};

for (int i = 0; i < jagged.length; i++) {
for (int j = 0; j < jagged[i].length; j++) {
System.out.print(jagged[i][j] + " ");
}
System.out.println();
}
// 输出:
// 1 2
// 3 4 5

若改用 jagged[0].length(固定为 2),第 1 行的第三个元素 5 会丢失。


常见操作

计算元素总和

int[][] nums = {{1, 2}, {3, 4}, {5, 6}};
int sum = 0;
for (int[] row : nums) {
for (int num : row) {
sum += num;
}
}
System.out.println(sum); // 21

查找最大值

int[][] nums = {{12, 8}, {9, 25}, {7, 18}};
int max = nums[0][0];
for (int[] row : nums) {
for (int num : row) {
if (num > max) {
max = num;
}
}
}
System.out.println(max); // 25


内存结构

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

内存布局:

  • 栈:变量 arr 存外层数组的地址
  • 外层数组(堆):长度 2,每个元素存一个内层数组的地址
  • 内层数组 1(堆):长度 3 的 int 数组,元素默认值 0
  • 内层数组 2(堆):长度 3 的 int 数组,元素默认值 0

关键结论:Java 二维数组不是连续矩形内存,而是「外层引用数组 + 多个独立一维数组」的组合,因此每行可独立分配不同长度,访问元素需两次寻址。


注意事项

问题

触发条件

异常类型

索引越界

i >= arr.length 或 j >= arr[i].length

ArrayIndexOutOfBoundsException

空指针

定义了行但未初始化:int[][] arr = new int[2][]; arr[0][0] = 1;

NullPointerException

遍历遗漏

不规则数组用 arr[0].length 作为所有行列数上限

逻辑错误

索引范围示例:

int[][] arr = new int[3][4];
// 行索引:0 ~ 2 (arr.length – 1)
// 列索引:0 ~ 3 (arr[0].length – 1)
// arr[3][0] → ArrayIndexOutOfBoundsException
// arr[0][4] → ArrayIndexOutOfBoundsException


典型应用场景

场景

示例

表格数据

学生成绩表、商品信息表、员工考勤

数学矩阵

矩阵加法、矩阵乘法、矩阵转置

游戏棋盘

五子棋、扫雷、贪吃蛇

多层分类

省→市→区、大类→小类→商品

赞(0)
未经允许不得转载:171主机测评 » 7. Java 二维数组
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址