20、Java 数组与集合:高效处理多值的技巧

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++; }
AI 代码审查Review工具 是一个旨在自动化代码审查流程的工具。它通过集成版本控制系统(如 GitHub 和 GitLab)的 Webhook,利用大型语言模型(LLM)对代码变更进行分析,并将审查意见反馈到相应的 Pull Request 或 Merge Request 中。此外,它还支持将审查结果通知到企业微信等通讯工具。 一个基于 LLM 的自动化代码审查助手。通过 GitHub/GitLab Webhook 监听 PR/MR 变更,调用 AI 分析代码,并将审查意见自动评论到 PR/MR,同时支持种通知渠道。 主要功能 平台支持: 集成 GitHub 和 GitLab Webhook,监听 Pull Request / Merge Request 事件。 智能审查模式: 详细审查 (/github_webhook, /gitlab_webhook): AI 对每个变更文件进行分析,旨在找出具体问题。审查意见会以结构化的形式(例如,定位到特定代码行、问题分类、严重程度、分析和建议)逐条评论到 PR/MR。AI 模型会输出 JSON 格式的分析结果,系统再将其转换为条独立的评论。 通用审查 (/github_webhook_general, /gitlab_webhook_general): AI 对每个变更文件进行整体性分析,并为每个文件生成一个 Markdown 格式的总结性评论。 自动化流程: 自动将 AI 审查意见(详细模式下为条,通用模式下为每个文件一条)发布到 PR/MR。 在所有文件审查完毕后,自动在 PR/MR 中发布一条总结性评论。 即便 AI 未发现任何得报告的问题,也会发布相应的友好提示和总结评论。 异步处理审查任务,快速响应 Webhook。 通过 Redis 防止对同一 Commit 的重复审查。 灵活配置: 通过环境变量设置基
【直流微电网】径向直流微电网的状态空间建模线性化:一种耦合DC-DC变换器状态空间平均模型的方法 (Matlab代码实现)内容概要:本文介绍了径向直流微电网的状态空间建模线性化方法,重点提出了一种基于耦合DC-DC变换器的状态空间平均模型的建模策略。该方法通过数学建模手段对直流微电网系统进行精确的状态空间描述,并对其进行线性化处理,以便于系统稳定性分析控制器设计。文中结合Matlab代码实现,展示了建模仿真过程,有助于研究人员理解和复现相关技术,推动直流微电网系统的动态性能研究工程应用。; 适合人群:具备电力电子、电力系统或自动化等相关背景,熟悉Matlab/Simulink仿真工具,从事新能源、微电网或智能电网研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①掌握直流微电网的动态建模方法;②学习DC-DC变换器在耦合条件下的状态空间平均建模技巧;③实现系统的线性化分析并支持后续控制器设计(如电压稳定控制、功率分配等);④为科研论文撰写、项目仿真验证提供技术支持代码参考。; 阅读建议:建议读者结合Matlab代码逐步实践建模流程,重点关注状态变量选取、平均化处理和线性化推导过程,同时可扩展应用于更复杂的直流微电网拓扑结构中,提升系统分析设计能力。
内容概要:本文介绍了基于物PINN驱动的三维声波波动方程求解(Matlab代码实现)理信息神经网络(PINN)求解三维声波波动方程的Matlab代码实现方法,展示了如何利用PINN技术在无需大量标注数据的情况下,结合物理定律约束进行偏微分方程的数求解。该方法将神经网络物理方程深度融合,适用于复杂波动问题的建模仿真,并提供了完整的Matlab实现方案,便于科研人员理解和复现。此外,文档还列举了个相关科研方向和技术服务内容,涵盖智能优化算法、机器学习、信号处理、电力系统等个领域,突出其在科研仿真中的广泛应用价。; 适合人群:具备一定数学建模基础和Matlab编程能力的研究生、科研人员及工程技术人员,尤其适合从事计算物理、声学仿真、偏微分方程数解等相关领域的研究人员; 使用场景及目标:①学习并掌握PINN在求解三维声波波动方程中的应用原理实现方式;②拓展至其他物理系统的建模仿真,如电磁场、热传导、流体力学等问题;③为科研项目提供可复用的代码框架和技术支持参考; 阅读建议:建议读者结合文中提供的网盘资源下载完整代码,按照目录顺序逐步学习,重点关注PINN网络结构设计、损失函数构建及物理边界条件的嵌入方法,同时可借鉴其他案例提升综合仿真能力。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值