一、数组基础:为什么需要数组?
想象一个场景:你需要存储班级 30 名学生的姓名,如果用变量存储,需要定义name1、name2……name30共 30 个变量,不仅繁琐,后续操作(如随机点名)也非常麻烦。这时候,数组就能帮我们解决这个问题。
1. 什么是数组?
数组是一个数据容器,专门用于存储一批同类型的数据。它就像一个有多个格子的盒子,每个格子存储一个数据,所有格子的数据类型必须一致。
生活 analogy:数组就像药盒,每个格子放一种药片(同类型),通过格子编号(索引)可以快速找到对应药片。
2. 数组的核心特点
- 存储同类型数据:数组中的所有元素必须是相同数据类型
- 固定长度:一旦创建,长度不能改变
- 索引访问:通过索引(从 0 开始的编号)访问元素
- 连续存储:在内存中连续分配空间,访问效率高
二、一维数组:基础用法全解析
1. 数组的定义方式
Java 中定义一维数组有两种方式:静态初始化和动态初始化。
(1)静态初始化:创建时直接指定元素
适用于已知具体元素值的场景,语法:
// 完整格式
数据类型[] 数组名 = new 数据类型[]{元素1, 元素2, 元素3, ...};
// 简化格式(推荐)
数据类型[] 数组名 = {元素1, 元素2, 元素3, ...};
示例:存储班级学生姓名
// 存储5名学生姓名
String[] students = {"张三", "李四", "王五", "赵六", "孙七"};
// 存储6个整数
int[] scores = {90, 85, 95, 78, 88, 92};
(2)动态初始化:先指定长度,后赋值
适用于已知元素数量但不确定具体值的场景,语法:
数据类型[] 数组名 = new 数据类型[长度];
示例:创建可存储 8 名学生姓名的数组
// 定义长度为8的字符串数组(初始值为null)
String[] names = new String[8];
// 后续为数组元素赋值
names[0] = "张三";
names[1] = "李四";
// ... 赋值其他元素
动态初始化的默认值规则
动态初始化时,数组元素会被自动赋予默认值,规则如下:
数据类型分类
具体类型
默认值
整数类型
byte、short、int、long
0
浮点类型
float、double
0.0
字符类型
char
'\u0000'(空字符)
布尔类型
boolean
false
引用类型
String、数组等
null
2. 数组的访问与操作
(1)访问数组元素
通过索引访问数组元素,索引从 0 开始,最大值为数组长度-1:
String[] students = {"张三", "李四", "王五"};
System.out.println(students[0]); // 输出:张三(访问第1个元素)
System.out.println(students[1]); // 输出:李四(访问第2个元素)
(2)修改数组元素
直接通过索引重新赋值:
int[] scores = {90, 85, 95};
scores[1] = 92; // 将第2个元素修改为92
System.out.println(scores[1]); // 输出:92
(3)获取数组长度
通过数组名.length获取数组长度(元素个数):
String[] students = {"张三", "李四", "王五"};
System.out.println(students.length); // 输出:3(数组有3个元素)
3. 数组的遍历:访问所有元素
遍历是指逐个访问数组中的所有元素,通常使用for循环实现:
(1)普通 for 循环遍历
int[] scores = {90, 85, 95, 78};
// i从0开始,小于数组长度
for (int i = 0; i < scores.length; i++) {
System.out.println("第" + (i+1) + "个元素:" + scores[i]);
}
输出结果:
第1个元素:90
第2个元素:85
第3个元素:95
第4个元素:78
(2)增强 for 循环(foreach)遍历
简化遍历语法,无需关注索引:
String[] students = {"张三", "李四", "王五"};
// 逐个取出数组元素赋值给student变量
for (String student : students) {
System.out.println(student);
}
输出结果:
张三
李四
王五
4. 数组常见操作实战
(1)求数组中的最大值 / 最小值
思路:先假设第一个元素为最值,再遍历数组比较更新。
public class ArrayDemo {
public static void main(String[] args) {
int[] scores = {85, 92, 78, 90, 88};
// 求最大值
int max = scores[0]; // 假设第一个元素是最大值
for (int i = 1; i < scores.length; i++) {
if (scores[i] > max) {
max = scores[i]; // 发现更大值则更新
}
}
// 求最小值
int min = scores[0]; // 假设第一个元素是最小值
for (int i = 1; i < scores.length; i++) {
if (scores[i] < min) {
min = scores[i]; // 发现更小值则更新
}
}
System.out.println("最大值:" + max); // 输出:92
System.out.println("最小值:" + min); // 输出:78
}
}
(2)数组元素搜索(查找指定值的索引)
思路:遍历数组,对比元素值与目标值,找到则返回索引。
public class ArraySearch {
public static void main(String[] args) {
String[] students = {"张三", "李四", "王五", "赵六"};
String target = "王五";
int index = -1; // 初始值设为-1(表示未找到)
// 遍历数组查找目标
for (int i = 0; i < students.length; i++) {
if (students[i].equals(target)) {
index = i; // 找到目标,记录索引
break; // 退出循环
}
}
if (index != -1) {
System.out.println(target + "的索引是:" + index); // 输出:王五的索引是:2
} else {
System.out.println("未找到" + target);
}
}
}
(3)随机点名小程序
综合应用:用数组存储学生姓名,随机生成索引实现随机点名。
import java.util.Random;
public class RandomCall {
public static void main(String[] args) {
// 存储班级学生姓名
String[] students = {
"张三", "李四", "王五", "赵六", "孙七",
"周八", "吴九", "郑十", "王十一", "冯十二"
};
// 生成随机索引(0 ~ 数组长度-1)
Random random = new Random();
int randomIndex = random.nextInt(students.length);
// 输出随机选中的学生
System.out.println("本次点名选中:" + students[randomIndex]);
}
}
三、二维数组:数组中的数组
当需要存储表格形式的数据(如班级座位表、矩阵数据)时,一维数组就不够用了,这时候需要用到二维数组。
1. 什么是二维数组?
二维数组是数组中的每个元素都是一个一维数组,可以理解为 "数组的数组"。它就像一个表格,有行和列的概念。
生活 analogy:二维数组就像 Excel 表格,每个行是一个一维数组,每个单元格通过 "行号 + 列号" 定位。
2. 二维数组的定义方式
(1)静态初始化:直接指定元素
// 完整格式
数据类型[][] 数组名 = new 数据类型[][]{
{元素1, 元素2, ...}, // 第一行
{元素1, 元素2, ...}, // 第二行
...
};
// 简化格式(推荐)
数据类型[][] 数组名 = {
{元素1, 元素2, ...},
{元素1, 元素2, ...},
...
};
示例:存储班级座位表
// 4行3列的座位表
String[][] seats = {
{"张无忌", "赵敏", "周芷若"}, // 第一行
{"张三丰", "宋远桥", "殷梨亭"}, // 第二行
{"灭绝", "陈昆", "玄冥二老"}, // 第三行
{"杨逍", "纪晓芙", "韦一笑"} // 第四行
};
(2)动态初始化:指定行数和列数
// 方式1:指定行数和列数(每行列数相同)
数据类型[][] 数组名 = new 数据类型[行数][列数];
// 方式2:先指定行数,后续再定义每行的列数(每行列数可不同)
数据类型[][] 数组名 = new 数据类型[行数][];
示例:
// 方式1:3行4列的整数数组
int[][] matrix = new int[3][4];
// 方式2:先定义3行,每行列数后续指定
int[][] irregular = new int[3][];
irregular[0] = new int[2]; // 第一行2列
irregular[1] = new int[5]; // 第二行5列
irregular[2] = new int[3]; // 第三行3列
3. 二维数组的访问与遍历
(1)访问元素
通过数组名[行索引][列索引]访问元素:
String[][] seats = {
{"张无忌", "赵敏", "周芷若"},
{"张三丰", "宋远桥", "殷梨亭"}
};
// 访问第二行第三列的元素(注意索引从0开始)
System.out.println(seats[1][2]); // 输出:殷梨亭
(2)遍历二维数组
需要使用嵌套循环:外层循环遍历行,内层循环遍历每行的元素。
String[][] seats = {
{"张无忌", "赵敏", "周芷若"},
{"张三丰", "宋远桥", "殷梨亭"},
{"灭绝", "陈昆", "玄冥二老"}
};
// 外层循环遍历行
for (int i = 0; i < seats.length; i++) {
System.out.print("第" + (i+1) + "行:");
// 内层循环遍历当前行的元素
for (int j = 0; j < seats[i].length; j++) {
System.out.print(seats[i][j] + " ");
}
System.out.println(); // 换行
}
输出结果:
第1行:张无忌 赵敏 周芷若
第2行:张三丰 宋远桥 殷梨亭
第3行:灭绝 陈昆 玄冥二老
四、综合实战案例
案例 1:简易斗地主洗牌程序
需求:创建一副扑克牌(54 张)并实现洗牌功能。
import java.util.Random;
public class PokerGame {
public static void main(String[] args) {
// 1. 准备扑克牌
String[] colors = {"♠", "♥", "♦", "♣"};
String[] numbers = {"2", "A", "K", "Q", "J", "10", "9", "8", "7", "6", "5", "4", "3"};
String[] poker = new String[54]; // 54张牌
// 存储普通牌(52张)
int index = 0;
for (String color : colors) {
for (String number : numbers) {
poker[index++] = color + number;
}
}
// 存储大小王
poker[52] = "大王";
poker[53] = "小王";
System.out.println("洗牌前:");
for (int i = 0; i < poker.length; i++) {
System.out.print(poker[i] + " ");
if ((i+1) % 13 == 0) System.out.println(); // 每13张换行
}
// 2. 洗牌:打乱数组顺序
Random random = new Random();
for (int i = 0; i < poker.length; i++) {
// 生成随机索引
int randomIndex = random.nextInt(poker.length);
// 交换当前元素和随机索引元素
String temp = poker[i];
poker[i] = poker[randomIndex];
poker[randomIndex] = temp;
}
System.out.println("\n洗牌后:");
for (int i = 0; i < poker.length; i++) {
System.out.print(poker[i] + " ");
if ((i+1) % 13 == 0) System.out.println(); // 每13张换行
}
}
}
案例 2:学生成绩统计系统
需求:使用二维数组存储多名学生的多门成绩,计算每个学生的平均分。
public class ScoreStatistics {
public static void main(String[] args) {
// 二维数组:每行代表一个学生的成绩(语文、数学、英语)
double[][] scores = {
{85, 92, 78}, // 学生1
{90, 88, 95}, // 学生2
{76, 80, 82}, // 学生3
{92, 79, 88} // 学生4
};
// 遍历数组计算平均分
for (int i = 0; i < scores.length; i++) {
double sum = 0; // 总分
// 计算当前学生的总分
for (int j = 0; j < scores[i].length; j++) {
sum += scores[i][j];
}
// 计算平均分
double avg = sum / scores[i].length;
System.out.println("学生" + (i+1) + "的平均分:" + avg);
}
}
}
输出结果:
学生1的平均分:85.0
学生2的平均分:91.0
学生3的平均分:79.33333333333333
学生4的平均分:86.33333333333333
五、数组常见问题与注意事项
1. 数组索引越界异常(ArrayIndexOutOfBoundsException)
当访问的索引超出0 ~ 数组长度-1范围时抛出,是初学者最常见的错误之一。
int[] arr = {10, 20, 30};
System.out.println(arr[3]); // 错误:arr长度为3,最大索引为2
2. 空指针异常(NullPointerException)
当数组未初始化或赋值为null时访问元素抛出:
String[] arr = null;
System.out.println(arr[0]); // 错误:arr为null,未指向实际数组
String[] arr2 = new String[3];
System.out.println(arr2[0].length()); // 错误:arr2[0]为null
3. 数组长度不可变
数组一旦创建,长度就固定了,不能动态增加或减少:
int[] arr = {1, 2, 3};
arr.length = 5; // 错误:不能修改数组长度
总结
数组是 Java 中处理批量数据的基础工具,本文主要介绍了:
- 一维数组的两种初始化方式(静态 / 动态)及基本操作
- 数组遍历、求最值、搜索等常见应用
- 二维数组的概念、定义和嵌套遍历
- 通过实战案例(洗牌、成绩统计)巩固知识点
学习数组的关键是多练习遍历和元素操作,理解索引的作用。数组虽然长度固定,但却是理解更复杂数据结构(如集合框架)的基础。建议初学者多敲代码,尝试修改案例中的需求(如给洗牌程序增加发牌功能),在实践中加深理解。
如果本文对你有帮助,欢迎点赞收藏~ 有任何问题欢迎在评论区交流!