从0开始学习Java+AI知识点记录和总结-4.程序的数据存储

64 阅读9分钟

一、数组基础:为什么需要数组?

想象一个场景:你需要存储班级 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 中处理批量数据的基础工具,本文主要介绍了:

  • 一维数组的两种初始化方式(静态 / 动态)及基本操作
  • 数组遍历、求最值、搜索等常见应用
  • 二维数组的概念、定义和嵌套遍历
  • 通过实战案例(洗牌、成绩统计)巩固知识点

学习数组的关键是多练习遍历和元素操作,理解索引的作用。数组虽然长度固定,但却是理解更复杂数据结构(如集合框架)的基础。建议初学者多敲代码,尝试修改案例中的需求(如给洗牌程序增加发牌功能),在实践中加深理解。

如果本文对你有帮助,欢迎点赞收藏~ 有任何问题欢迎在评论区交流!