Java基础快速入门:二维数组

本文纲要

  1. 二维数组概述
  2. 二维数组的动态初始化
  3. 二维数组访问元素的细节
  4. 二维数组的静态初始化
  5. 二维数组的遍历
  6. 二维数组求和

二维数组概述

二维数组本质上是一个容器,与一维数组不同的是,它内部存储的是一维数组(更准确地说,存储的是一维数组的引用)。可以把二维数组理解成一个“大容器”,里面装着多个“小容器”。

例如,有三个箱子分别装着啤酒,每个箱子就是一个一维数组;现在用一辆货车把这三个箱子一起运走,货车就相当于一个二维数组,它装载了三个一维数组。

应用场景:当一组数据需要按多个分组进行管理时,就很适合使用二维数组。例如,某公司按季度统计销售额,每个季度包含多个月份的数据,就可以用一个二维数组存储,其中每个一维数组代表一个季度的数据。

二维数组的动态初始化

1 ) 定义格式

数据类型[][] 数组名 = new 数据类型[m][n];

m:表示这个二维数组中可以存放多少个一维数组;
n:表示每个一维数组中可以存放多少个元素。

其他不太常用的写法:

数据类型 数组名[][] = new 数据类型[m][n];
数据类型[] 数组名[] = new 数据类型[m][n];

这三种写法都能创建二维数组,但第一种最常见。

示例

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

上述代码创建了一个 int 类型的二维数组,可以存放 3 个一维数组,每个一维数组又可以存放 3 个 int 元素。

打印二维数组名

System.out.println(arr);  // 例如输出:[[I@10f87f48 
  • [[:中括号的数量代表数组的维度,两个中括号表示二维数组(一维数组为一个中括号);
  • I:表示数组中存储的元素类型为 int;
  • @:分隔符,无实际意义;
  • 10f87f48:十六进制内存地址。

动态初始化时的默认值

使用 new int[3][3] 动态初始化后,系统会自动为每个元素赋予默认值,int 类型的默认值为 0。以下代码可以验证:

System.out.println(arr[0][0]);  // 0
System.out.println(arr[1][1]);  // 0 
System.out.println(arr[2][2]);  // 0

访问与存储元素

访问二维数组中的元素需要使用两个索引:

arr[0][0] = 11;  // 存储到第1个一维数组的第1个位置
arr[1][2] = 33;  // 存储到第2个一维数组的第3个位置
System.out.println(arr[0][0]);  // 取出第1个一维数组的第1个元素

注意事项:如果只使用一个索引,例如 arr[0],获取到的是该位置的一维数组的内存地址,而不是具体的元素值。

System.out.println(arr[0]);  // 一维数组的地址,如 [I@...  (一个中括号)

因此,二维数组实际上存储的是每个一维数组的引用(内存地址)

二维数组访问元素的细节

能否存入提前创建好的一维数组?

可以。例如:

int[] arr1 = {11, 22, 33};
int[] arr2 = {44, 55, 66};
int[] arr3 = {77, 88, 99, 100};  // 注意该数组长度为4,超过了原定长度3
 
int[][] arr = new int[3][3];
 
arr[0] = arr1;
arr[1] = arr2;
arr[2] = arr3;  // 将 arr3 的引用赋给二维数组的第3个位置
 
System.out.println(arr[1][2]);  // 66 
System.out.println(arr[2][3]);  // 100,可以正常访问 

此时,arr[2] 原本指向一个长度为3的新数组,但被替换成了 arr3 的引用,因此现在 arr[2] 指向的是长度为4的数组。所以 arr[2][3] 可以正常访问,不会出现索引越界。
为什么这样不会报错,而直接赋值会报错?

如果直接使用传统方式:

arr[2][3] = 100;  // 数组索引越界异常 ArrayIndexOutOfBoundsException

动态初始化 new int[3][3] 时,JVM 会立即创建好三个长度为3的一维数组,并将它们的引用存入二维数组。此时 arr[2] 指向的数组长度固定为3,索引只能到2,因此访问索引3会越界。

而如果我们先定义好一个长度为4的数组,再通过 arr[2] = arr3 替换引用,arr[2] 就不再指向原来的长度为3的数组,而是指向新的长度为4的数组,因此可以访问索引3。

原理图(使用 Mermaid 演示内存引用替换):

堆内存

栈内存

索引0

索引1

索引2

arr[2] = arr3 后

二维数组 arr

一维数组 arr1

一维数组 arr2

一维数组 arr3

二维数组对象: 3个引用

一维数组对象: 长度3

一维数组对象: 长度3

一维数组对象: 长度3

一维数组 arr3: 长度4

最初,arr[2] 指向一个长度为3的对象;执行 arr[2] = arr3 后,arr[2] 改为指向 arr3 所指向的长度为4的对象,因此可以访问 arr[2][3]。

二维数组的静态初始化

完整格式

数据类型[][] 数组名 = new 数据类型[][]{{元素1, 元素2...}, {元素1, 元素2...}...};

简化格式(常用)

数据类型[][] 数组名 = {{元素1, 元素2...}, {元素1, 元素2...}...};

示例

int[][] arr = {{11, 22, 33}, {44, 55, 66}};
System.out.println(arr[0][2]);  // 33

也可以先创建好一维数组,再组合:

int[] arr1 = {11, 22, 33};
int[] arr2 = {44, 55, 66};
int[][] array = {arr1, arr2};
System.out.println(array[0][2]);  // 33

二维数组的遍历

需求:已知二维数组 arr = {{11, 22, 33}, {33, 44, 55}},遍历并取出所有元素。

步骤:

  1. 遍历二维数组,取出每一个一维数组;
  2. 对每个一维数组继续进行遍历,获取内部存储的每一个元素。

代码实现:

int[][] arr = {{11, 22, 33}, {33, 44, 55}};
 
// 外层循环:遍历二维数组,得到每一个一维数组 arr[i]
for (int i = 0; i < arr.length; i++) {
    // 内层循环:遍历当前一维数组,得到每一个元素
    for (int j = 0; j < arr[i].length; j++) {
        System.out.println(arr[i][j]);
    }
}

理解要点:arr[i] 是一个一维数组,arr[i].length 是该一维数组的长度,arr[i][j] 就是具体的元素值。

二维数组求和

1 )需求

某公司季度和月份统计数据如下(单位:万元),求全年总销售额。
第一季度:22, 66, 44
第二季度:77, 33, 88
第三季度:25, 45, 65
第四季度:11, 66, 99

2 ) 思路

  1. 定义求和变量 sum,初始化为 0;
  2. 使用二维数组存储数据,每个季度为一个一维数组,再将四个一维数组装入二维数组;
  3. 嵌套循环遍历二维数组,累加每个元素到 sum;
  4. 输出结果。

3 ) 代码实现

int sum = 0;
int[][] arr = {
    {22, 66, 44},
    {77, 33, 88},
    {25, 45, 65},
    {11, 66, 99}
};
 
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 + "万元");  // 641

总结

二维数组是存储一维数组的容器,适合处理分组数据
动态初始化:new int[m][n],系统自动分配空间并赋予默认值,访问时使用两个索引
替换引用:arr[i] = existingArray 可以改变二维数组某位置指向的一维数组对象,从而突破原先的长度限制
静态初始化:使用 {{...}, {...}} 简化格式,直接在声明时赋值
遍历:嵌套循环,外层遍历二维数组,内层遍历每一个一维数组
求和:在遍历过程中累加即可

掌握这些内容,就可以游刃有余地使用二维数组解决实际问题了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值