news 2026/4/16 15:55:29

结构体(Java 类)实战题解笔记(持续更新)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
结构体(Java 类)实战题解笔记(持续更新)

前言

Java也可以有结构体吗?
在 Java 中并没有直接的「结构体」概念,但可以通过自定义类(class)实现结构体的核心功能——封装一组具有关联关系的数据。本笔记通过实战题目,讲解如何用自定义类存储复杂数据、处理业务逻辑,后续可直接沿用该笔记格式补充更多同类题目。

题目1:歌唱比赛得分统计(求最高平均分)

题目核心需求

统计 n 名同学的歌唱比赛得分,每位同学有 m 名评委打分,得分规则为「去掉一个最高分、一个最低分后求平均值」,最终输出所有同学中的最高平均分(保留 2 位小数)。

解题思路

  1. 封装数据模型:定义Student类,封装每位同学的评委分数数组、最高分、最低分、总分(去高低分后)、平均分。
  2. 初始化数据:创建 n 个Student实例,每个实例初始化对应长度的评委分数数组。
  3. 读取并计算数据:逐行读取评委打分,同时计算该同学的最高分、最低分、原始总分;后续扣除高低分,计算有效平均分。
  4. 排序找最大值:通过冒泡排序对所有同学的平均分进行升序排列,排序后最后一个元素即为最高平均分。
  5. 格式化输出:保留 2 位小数输出结果。

核心代码解析

packageStruct;importjava.util.Scanner;// 封装学生歌唱比赛数据的类(对应结构体功能)classStudent{intid;// 可选:学生编号,本题未要求使用inta[];// 存储m名评委的打分intmax=-1;// 最高分,初始值低于最小可能得分(0)intmin=11;// 最低分,初始值高于最大可能得分(10)doubleavg;// 有效平均分(去高低分后)doublesum;// 原始总分(所有评委打分之和)}publicclassMain{publicstaticvoidmain(String[]args){Scannersc=newScanner(System.in);intn=sc.nextInt();// 学生人数intm=sc.nextInt();// 评委人数Studentsts[]=newStudent[n];// 学生数组,存储所有学生信息// 步骤1:初始化学生数组和每个学生的分数数组for(inti=0;i<n;i++){sts[i]=newStudent();// 必须实例化每个Student,否则会出现空指针异常sts[i].a=newint[m];// 初始化每个学生的评委分数数组}// 步骤2:读取打分并计算每个学生的核心数据(max、min、sum、avg)for(inti=0;i<n;i++){for(intj=0;j<m;j++){sts[i].a[j]=sc.nextInt();// 读取单个评委打分sts[i].sum+=sts[i].a[j];// 累加原始总分// 更新最高分和最低分sts[i].max=Math.max(sts[i].a[j],sts[i].max);sts[i].min=Math.min(sts[i].a[j],sts[i].min);}// 计算有效总分(去掉最高分和最低分)sts[i].sum-=(sts[i].max+sts[i].min);// 计算有效平均分,*1.0 确保除法结果为小数,避免整数除法丢失精度sts[i].avg=sts[i].sum*1.0/(m-2);}// 步骤3:冒泡排序(升序),将平均分最低的放前面,最高的放后面for(inti=0;i<n-1;i++){for(intj=0;j<n-1-i;j++){if(sts[j].avg>sts[j+1].avg){// 交换两个学生对象(整体交换,无需单独交换每个字段,体现类封装的优势)Studenttemp=sts[j];sts[j]=sts[j+1];sts[j+1]=temp;}}}// 步骤4:格式化输出最高平均分(保留2位小数)System.out.printf("%.2f\n",sts[n-1].avg);sc.close();}}
关键注意点
  1. 数组初始化Student sts[] = new Student[n]仅创建了数组容器,每个数组元素(Student对象)需要单独new Student()实例化,否则会抛出NullPointerException
  2. 数据类型精度:计算平均分时分母是m-2(整数),需要通过*1.0将分子转为浮点型,避免整数除法(直接舍弃小数部分)导致结果错误。
  3. 极值初始化:最高分max初始化为-1(低于最小可能得分 0),最低分min初始化为11(高于最大可能得分 10),确保能被评委打分正确覆盖。

输入输出示例

输入:

7 6 4 7 2 6 10 7 0 5 0 10 3 10 2 6 8 4 3 6 6 3 6 7 5 8 5 9 3 3 8 1 5 9 9 3 2 0 5 8 0 4 1 10

输出:

6.00

题目2:期末考试「旗鼓相当的对手」匹配

题目核心需求

给定 N 名同学的姓名和语、数、英成绩,找出所有「旗鼓相当的对手」组合:

  1. 每科成绩分差均不大于 5;
  2. 总分分差均不大于 10;
  3. 输出时满足字典序:第一个姓名字典序 < 第二个姓名,且组合整体按字典序排序。

解题思路

  1. 封装数据模型:定义Student2类,封装同学的姓名、三科成绩、总分。
  2. 读取并存储数据:读取 N 名同学的信息,实例化Student2对象并存入数组(输入已按字典序排列,数组天然保留该顺序)。
  3. 双重循环匹配组合:使用两层循环遍历所有i < j的同学组合(避免重复组合,且保证i在前j在后,符合字典序要求)。
  4. 判断对手条件:逐一验证三科分差和总分分差的条件,满足则输出对应姓名组合。
  5. 保证输出格式:因输入已按字典序排列,i < j的循环组合直接输出即可满足题目字典序要求。

核心代码解析

packageStruct;importjava.util.Scanner;// 封装学生期末考试数据的类(对应结构体功能)classStudent2{Stringname;// 学生姓名intchinese;// 语文成绩intmath;// 数学成绩intenglish;// 英语成绩intsum;// 三科总分}publicclassMain2{publicstaticvoidmain(String[]args){Scannersc=newScanner(System.in);intn=sc.nextInt();// 学生人数Student2sts[]=newStudent2[n];// 学生数组,存储所有学生信息// 步骤1:读取并初始化所有学生的信息for(inti=0;i<n;i++){sts[i]=newStudent2();// 实例化每个Student2对象,避免空指针异常// 处理换行符问题:nextInt()后未读取换行符,next()会自动跳过空白字符(包括换行、空格),此处可省略sc.nextLine()sts[i].name=sc.next();// 读取姓名(无空格,用next())sts[i].chinese=sc.nextInt();// 读取语文成绩sts[i].math=sc.nextInt();// 读取数学成绩sts[i].english=sc.nextInt();// 读取英语成绩sts[i].sum=sts[i].chinese+sts[i].math+sts[i].english;// 计算总分}// 步骤2:双重循环匹配「旗鼓相当的对手」(i < j 避免重复组合,且符合字典序)for(inti=0;i<n;i++){for(intj=i+1;j<n;j++){// 条件1:每科成绩分差不大于5booleanchineseOk=Math.abs(sts[i].chinese-sts[j].chinese)<=5;booleanmathOk=Math.abs(sts[i].math-sts[j].math)<=5;booleanenglishOk=Math.abs(sts[i].english-sts[j].english)<=5;// 条件2:总分分差不大于10booleansumOk=Math.abs(sts[i].sum-sts[j].sum)<=10;// 满足所有条件,输出组合if(chineseOk&&mathOk&&englishOk&&sumOk){System.out.println(sts[i].name+" "+sts[j].name);}}}sc.close();}}
关键注意点
  1. 避免重复组合:使用i < j的循环逻辑(外层i从 0 到 n-1,内层ji+1到 n-1),既不会出现<i,i>自身组合,也不会出现<j,i><i,j>重复的组合。
  2. 字典序保证:题目明确输入姓名按字典序排列,数组存储顺序与输入顺序一致,i < j对应的sts[i].name字典序必然小于sts[j].name,直接输出即可满足题目要求。
  3. 输入读取技巧:读取姓名使用sc.next()(适用于无空格的字符串),nextInt()next()会自动跳过空白字符(换行、空格),无需额外处理换行符问题(原代码中的if(i==0) sc.nextLine()是冗余的,可删除)。
  4. 分差计算:使用Math.abs()计算绝对值差,避免分差为负数导致判断条件错误。

输入输出示例

输入:

3 fafa 90 90 90 lxl 95 85 90 senpai 100 80 91

输出:

fafa lxl lxl senpai

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 13:06:10

【Linux系统】进程间通信:基于匿名管道实现进程池

1. 进程池介绍 ​ 1.1 核心定义 进程池&#xff08;Process Pool&#xff09; 是一种预创建复用式的进程管理技术&#xff0c;其本质是操作系统中预分配的进程资源容器。它包含两大核心组件&#xff1a; 资源进程&#xff1a;池中预先创建的空闲进程&#xff0c;随时待命执…

作者头像 李华
网站建设 2026/4/16 10:42:38

第 8 篇:适配器模式 (Adapter) —— 换芯片不换代码

专栏导读:适配器模式就像我们出国的“电源转换插头”。你(业务层)需要的是标准的 220V 两孔插座,而墙上(硬件层)提供的是美标、英标、欧标各种奇形怪状的插孔。适配器负责在中间做一次“翻译”,让你根本不需要关心墙后面是核电还是水电。 1. 场景还原 (The Pain) 假设你…

作者头像 李华
网站建设 2026/4/16 7:44:12

Python中 .whl 后缀文件的全称

你想了解Python中.whl后缀文件的全称&#xff0c;以及文件名各部分的含义&#xff0c;对吧&#xff1f; 首先先纠正一个小偏差&#xff0c;.whl的全称不是“啥”&#xff0c;而是Wheel&#xff08;字面意思是“轮子”&#xff09;&#xff0c;它是Python的一种预编译软件包格式…

作者头像 李华
网站建设 2026/4/16 7:43:47

Type-C 领夹麦的核心痛点与 PD 协议解决方案

领夹麦作为直播、录音场景的核心设备&#xff0c;长期面临三大技术瓶颈&#xff1a;传统单接口无法同时实现 “音频传输 快充供电”&#xff0c;导致直播中途断电&#xff1b;充电电流干扰音频信号&#xff0c;产生底噪&#xff1b;设备兼容性差&#xff0c;难以适配多品牌手机…

作者头像 李华
网站建设 2026/4/16 7:45:20

凌晨两点调 API 调到崩溃,直到 MCP 出现——AI 终于有了统一接口

凌晨两点&#xff0c;第三杯咖啡见底&#xff0c;我盯着屏幕上那堆 API 文档想骂人。 OpenAI 一套鉴权&#xff0c;Claude 一套格式&#xff0c;Gemini 又是另一套。每接入一个新模型&#xff0c;就得重写一遍适配层。这活儿跟给不同品牌手机各做一根充电线有什么区别&#xff…

作者头像 李华
网站建设 2026/4/16 7:48:34

Hive数据血缘分析:追踪数据来源的完整方案

Hive数据血缘分析&#xff1a;追踪数据来源的完整方案 摘要/引言 在大数据环境中&#xff0c;理解数据的来源和去向对于数据管理、质量保证以及合规性至关重要。Hive作为广泛使用的数据仓库工具&#xff0c;其数据血缘分析能够帮助数据工程师和分析师追溯数据从原始输入到最终…

作者头像 李华