Java 数组与集合:高效处理多值的技巧
1. 引入数组概念
想象有一家名为 Java Motel 的旅馆,它有 10 个房间,房间编号从 0 到 9。现在要记录每个房间的客人数量,如果声明 10 个变量来分别存储,代码会变得冗长且难以维护:
int guestsInRoomNum0, guestsInRoomNum1, guestsInRoomNum2,
guestsInRoomNum3, guestsInRoomNum4, guestsInRoomNum5,
guestsInRoomNum6, guestsInRoomNum7, guestsInRoomNum8,
guestsInRoomNum9;
而且,要读取每个变量的值,需要多次复制
nextInt
方法,效率低下。
更好的解决方案是使用数组。数组就像 Java Motel 的一排房间,每个房间可以存储一个值。在 Java 中,可以这样声明一个包含 10 个元素的整数数组:
int guests[] = new int[10];
也可以将其拆分为两条语句:
int guests[];
guests = new int[10];
在创建数组时,需要指定数组的元素数量,数组的索引从 0 开始,到元素数量减 1 结束。例如,上述数组的元素分别为
guests[0]
到
guests[9]
。
在数组声明中,方括号可以放在变量名之前或之后,即
int guests[]
和
int[] guests
是等效的。
2. 分两步创建数组
创建数组的两条语句
int guests[]
和
guests = new int[10]
有不同的作用:
-
int guests[]
:这是一个声明语句,它为数组预留了一个名称,但并没有为数组分配内存空间,只是设置了
guests
变量,此时该变量还不指向一个真正的数组。
-
guests = new int[10]
:这是一个赋值语句,它为数组在计算机内存中分配了 10 个
int
类型的空间。
graph LR
A[int guests[]] --> B(声明数组名称)
C[guests = new int[10]] --> D(分配内存空间)
3. 向数组中存储值
创建数组后,可以向数组的元素中存储值。例如,要将房间 6 的客人数量设为 4,可以这样写:
guests[6] = 4;
如果要将 10 对夫妇(每对 2 人)分别安排到 10 个房间,可以使用
for
循环:
for (int roomNum = 0; roomNum < 10; roomNum++) {
guests[roomNum] = 2;
}
如果客人数量不是固定的,可以从数据库或文本文件中读取客人数量。以下是从文本文件
GuestList.txt
中读取客人数量的示例代码:
import static java.lang.System.out;
import java.util.Scanner;
import java.io.File;
import java.io.IOException;
class ShowGuests {
public static void main(String args[])
throws IOException {
int guests[] = new int[10];
Scanner diskScanner =
new Scanner(new File("GuestList.txt"));
for(int roomNum = 0; roomNum < 10; roomNum++) {
guests[roomNum] = diskScanner.nextInt();
}
out.println("Room\tGuests");
for(int roomNum = 0; roomNum < 10; roomNum++) {
out.print(roomNum);
out.print("\t");
out.println(guests[roomNum]);
}
}
}
上述代码中有两个
for
循环,第一个循环用于读取客人数量,第二个循环用于输出房间号和客人数量。
每个数组都有一个内置的
length
字段,它表示数组的元素数量。在上述代码中,
guests.length
的值为 10。
4. 转义序列的使用
在代码中,
print
和
println
方法使用了
\t
转义序列,它表示一个制表符。Java 中还有其他一些有用的转义序列,如下表所示:
| 序列 | 含义 |
| ---- | ---- |
|
\b
| 退格符 |
|
\t
| 水平制表符 |
|
\n
| 换行符 |
|
\f
| 换页符 |
|
\r
| 回车符 |
|
\"
| 双引号 |
|
\'
| 单引号 |
|
\\
| 反斜杠 |
5. 使用数组初始化器
除了上述方法,还可以使用数组初始化器来填充数组,这样就不需要显式地指定数组的元素数量。例如:
import static java.lang.System.out;
class ShowGuests {
public static void main(String args[]) {
int guests[] = {1, 4, 2, 0, 2, 1, 4, 3, 0, 2};
out.println("Room\tGuests");
for (int roomNum = 0; roomNum < 10; roomNum++) {
out.print(roomNum);
out.print("\t");
out.println(guests[roomNum]);
}
}
}
数组初始化器中可以包含表达式和字面量,例如
{1 + 3, keyboard.nextInt(), 2, 0, 2, 1, 4, 3, 0, 2}
也是合法的。
6. 使用增强
for
循环遍历数组
Java 提供了一种增强
for
循环,它不需要使用计数器或索引。以下是使用增强
for
循环遍历数组的示例代码:
import static java.lang.System.out;
class ShowGuests {
public static void main(String args[]) {
int guests[] = {1, 4, 2, 0, 2, 1, 4, 3, 0, 2};
int roomNum = 0;
out.println("Room\tGuests");
for (int numGuests : guests) {
out.print(roomNum++);
out.print("\t");
out.println(numGuests);
}
}
}
增强
for
循环的语法为
for (variable-type variable-name : range-of-values)
,其中
variable-type
是变量的类型,
variable-name
是变量名,
range-of-values
是要遍历的数组或集合。
需要注意的是,增强
for
循环中的变量存储的是数组元素的副本,而不是元素本身。因此,修改该变量的值不会影响数组中的元素。例如:
for (int numGuests : guests) {
numGuests += 1;
out.print(numGuests + " ");
}
out.println();
for (int numGuests : guests) {
out.print(numGuests + " ");
}
上述代码的输出为:
1 1 1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 0
7. 在数组中查找元素
假设在 Java Motel 中,有一群 5 人的客人想要入住,需要检查是否有空闲房间。如果有,将
GuestList.txt
文件中对应的 0 替换为 5。以下是实现该功能的代码:
import static java.lang.System.out;
import java.util.Scanner;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
class FindVacancy {
public static void main(String args[])
throws IOException {
Scanner keyboard = new Scanner(System.in);
Scanner diskScanner =
new Scanner(new File("GuestList.txt"));
int guests[] = new int[10];
int roomNum;
for (roomNum = 0; roomNum < 10; roomNum++) {
guests[roomNum] = diskScanner.nextInt();
}
roomNum = 0;
while (roomNum < 10 && guests[roomNum] != 0) {
roomNum++;
}
if (roomNum == 10) {
out.println("Sorry, no v cancy");
} else {
out.print("How many people for room ");
out.print(roomNum);
out.print("? ");
guests[roomNum] = keyboard.nextInt();
PrintStream listOut =
new PrintStream("GuestList.txt");
for (roomNum = 0; roomNum < 10; roomNum++) {
listOut.print(guests[roomNum]);
listOut.print(" ");
}
}
}
}
上述代码的执行流程如下:
1. 从
GuestList.txt
文件中读取每个房间的客人数量。
2. 查找第一个空闲房间(客人数量为 0)。
3. 如果找到空闲房间,询问要入住的人数,并将该房间的客人数量更新。
4. 将更新后的客人数量写回
GuestList.txt
文件。
graph LR
A(读取文件) --> B(查找空闲房间)
B --> C{是否找到?}
C -- 是 --> D(询问入住人数)
C -- 否 --> E(输出无空闲房间)
D --> F(更新客人数量)
F --> G(写入文件)
运行该代码时,可能会遇到某些 Java IDE 不会自动显示最新的
GuestList.txt
文件内容的问题,需要手动刷新文件显示。
通过以上方法,可以高效地处理数组,实现多值的存储、读取和查找。
Java 数组与集合:高效处理多值的技巧(续)
8. 数组操作总结
在前面的内容中,我们介绍了数组的创建、赋值、遍历和查找等操作。下面对这些操作进行总结:
-
数组创建
:可以使用一条语句
int guests[] = new int[10];
或两条语句
int guests[]; guests = new int[10];
来创建数组。
-
数组赋值
:可以使用索引逐个赋值,如
guests[6] = 4;
,也可以使用
for
循环批量赋值,如
for (int roomNum = 0; roomNum < 10; roomNum++) { guests[roomNum] = 2; }
,还可以使用数组初始化器
int guests[] = {1, 4, 2, 0, 2, 1, 4, 3, 0, 2};
。
-
数组遍历
:可以使用普通
for
循环
for (int roomNum = 0; roomNum < 10; roomNum++) { out.println(guests[roomNum]); }
或增强
for
循环
for (int numGuests : guests) { out.println(numGuests); }
。
-
数组查找
:可以使用
while
循环查找特定元素,如查找空闲房间
while (roomNum < 10 && guests[roomNum] != 0) { roomNum++; }
。
9. 数组操作的注意事项
在使用数组时,需要注意以下几点:
-
数组索引越界
:数组的索引从 0 开始,到
length - 1
结束。如果使用超出这个范围的索引,会抛出
ArrayIndexOutOfBoundsException
异常。例如,
int guests[] = new int[10]; guests[10] = 2;
会导致索引越界。
-
增强
for
循环的局限性
:增强
for
循环只能用于遍历数组或集合,不能用于修改数组元素。如前面示例所示,修改增强
for
循环中的变量不会影响数组中的元素。
-
文件操作异常
:在进行文件读写操作时,如从
GuestList.txt
文件中读取数据或写入数据,可能会抛出
IOException
异常,需要进行异常处理。
10. 数组操作的应用场景
数组在很多场景中都有广泛的应用,以下是一些常见的应用场景:
-
数据存储
:可以使用数组来存储一组相关的数据,如学生的成绩、员工的工资等。
-
批量处理
:通过
for
循环可以对数组中的元素进行批量处理,如计算数组元素的总和、平均值等。
-
查找和排序
:可以在数组中查找特定元素,也可以对数组进行排序,如冒泡排序、选择排序等。
11. 示例代码综合应用
下面是一个综合应用数组操作的示例代码,该代码实现了从文件中读取学生成绩,计算平均成绩,并找出最高分和最低分的功能:
import static java.lang.System.out;
import java.util.Scanner;
import java.io.File;
import java.io.IOException;
class StudentScores {
public static void main(String args[])
throws IOException {
Scanner diskScanner =
new Scanner(new File("scores.txt"));
int scores[] = new int[10];
int sum = 0;
int max = Integer.MIN_VALUE;
int min = Integer.MAX_VALUE;
// 读取成绩
for(int i = 0; i < 10; i++) {
scores[i] = diskScanner.nextInt();
sum += scores[i];
if (scores[i] > max) {
max = scores[i];
}
if (scores[i] < min) {
min = scores[i];
}
}
// 计算平均成绩
double average = (double) sum / scores.length;
// 输出结果
out.println("Average score: " + average);
out.println("Max score: " + max);
out.println("Min score: " + min);
}
}
上述代码的执行流程如下:
1. 从
scores.txt
文件中读取 10 个学生的成绩。
2. 计算成绩的总和、最高分和最低分。
3. 计算平均成绩。
4. 输出平均成绩、最高分和最低分。
graph LR
A(读取文件) --> B(计算总和、最高分和最低分)
B --> C(计算平均成绩)
C --> D(输出结果)
12. 总结
通过本文的介绍,我们学习了 Java 数组的基本概念和操作,包括数组的创建、赋值、遍历、查找等。同时,我们还了解了转义序列的使用、数组初始化器和增强
for
循环的特点。在实际应用中,数组可以用于存储和处理大量的数据,提高程序的效率。在使用数组时,需要注意数组索引越界、增强
for
循环的局限性和文件操作异常等问题。希望本文对你学习 Java 数组有所帮助。
| 操作类型 | 操作方法 | 示例代码 |
|---|---|---|
| 创建数组 | 一条语句 |
int guests[] = new int[10];
|
| 创建数组 | 两条语句 |
int guests[]; guests = new int[10];
|
| 数组赋值 | 逐个赋值 |
guests[6] = 4;
|
| 数组赋值 | 批量赋值 |
for (int roomNum = 0; roomNum < 10; roomNum++) { guests[roomNum] = 2; }
|
| 数组赋值 | 数组初始化器 |
int guests[] = {1, 4, 2, 0, 2, 1, 4, 3, 0, 2};
|
| 数组遍历 |
普通
for
循环
|
for (int roomNum = 0; roomNum < 10; roomNum++) { out.println(guests[roomNum]); }
|
| 数组遍历 |
增强
for
循环
|
for (int numGuests : guests) { out.println(numGuests); }
|
| 数组查找 |
while
循环
|
while (roomNum < 10 && guests[roomNum] != 0) { roomNum++; }
|
超级会员免费看
1129

被折叠的 条评论
为什么被折叠?



