上一篇
Java中计算平均成绩,可先收集所有成绩存入数组,然后遍历累加求和,最后除以成绩个数即可得到平均值。
核心思路
- 收集数据源:将需要计算的成绩存储在数组、列表或其他集合结构中;
- 遍历求和:循环累加所有元素的总和;
- 除以数量:用总和除以元素个数得到平均值;
- 处理边界情况:例如空数据集或非数字输入等异常场景。
基于数组的基础实现
假设我们有一组固定长度的成绩数据,可以使用基本类型数组配合for循环完成计算:
public class ScoreCalculator {
public static void main(String[] args) {
// 示例数据:5门课程的成绩
double[] scores = {85.5, 92.0, 78.3, 90.7, 88.9};
// 初始化总分为0
double sum = 0;
// 遍历数组累加分数
for (int i = 0; i < scores.length; i++) {
sum += scores[i];
}
// 计算平均值(注意避免除以零)
if (scores.length > 0) {
double average = sum / scores.length;
System.out.printf("平均成绩为: %.2f", average); // 输出保留两位小数
} else {
System.out.println("无有效成绩可计算!");
}
}
}
优点:简单直观,适合已知固定数量的场景;
️ 缺点:若动态增减成绩需重新创建新数组,灵活性较差。
使用动态集合(ArrayList)
当成绩数量不确定时,推荐使用List<Double>实现动态管理:
import java.util.ArrayList;
import java.util.List;
public class ListBasedAverage {
public static void main(String[] args) {
List<Double> scoreList = new ArrayList<>();
// 模拟添加多组成绩(实际开发中可通过用户输入/文件读取等方式填充)
scoreList.add(91.2);
scoreList.add(87.6);
scoreList.add(89.5);
scoreList.add(93.0);
// 调用工具类方法计算均值
double avg = calculateAverage(scoreList);
if (!Double.isNaN(avg)) {
System.out.println("动态列表的平均分:" + String.format("%.1f", avg));
}
}
/
通用的列表平均值计算函数
@param numbers 包含数值的列表
@return 若列表为空返回NaN,否则返回平均值
/
private static double calculateAverage(List<Double> numbers) {
if (numbers == null || numbers.isEmpty()) return Double.NaN;
double total = 0;
for (Double num : numbers) {
total += num != null ? num : 0; // 处理null值视为0分
}
return total / numbers.size();
}
}
增强功能点:
- 自动跳过
null元素(视为缺考); - 返回特殊值
Double.NaN标识无效运算; - 支持任意数量的成绩追加。
进阶优化方向对比表
| 特性 | 基础数组方案 | 动态集合方案 | Stream API流式处理 |
|---|---|---|---|
| 数据结构 | T[] | List | Collection<? extends Number> |
| 空数据处理能力 | 需手动判断length>0 | isEmpty()+容错机制 | peek().filter(Objects::nonNull) |
| 代码简洁度 | |||
| 并行计算支持 | (parallelStream()) | ||
| 适用场景 | 静态小规模数据 | 中等规模动态数据 | 大数据量高效聚合 |
现代写法:Java 8+ Stream API
利用函数式编程特性可实现一行代码解决:
import java.util.;
import java.util.stream.Collectors;
public class StreamDemo {
public static void main(String[] args) {
OptionalDouble optionalAvg = Arrays.asList(85, 90, 76, 88, 92)
.stream()
.mapToInt(Integer::intValue)
.average();
optionalAvg.ifPresentOrElse(
avg -> System.out.println("流式API结果:" + avg),
() -> System.out.println("没有可用的成绩记录")
);
}
}
关键点解析:
mapToInt()将对象转为基本类型提升性能;average()返回OptionalDouble天然防NPE;ifPresentOrElse优雅处理空值情况。
常见错误排查指南
| 现象 | 原因分析 | 解决方案 |
|---|---|---|
| ArithmeticException | 除数为零(空数组) | 添加非空校验逻辑 |
| TypeMismatch | 混用不同精度类型(int/double) | 统一使用double进行浮点运算 |
| Inconsistent Results | 未考虑权重因素 | 根据需求调整计算公式 |
| Precision Loss | 多次累加导致精度丢失 | 改用BigDecimal高精度计算库 |
FAQs
Q1: 如果某些科目占比不同怎么办?比如平时作业占30%,期末考试占70%?
A: 此时不能直接取简单平均,应采用加权平均公式:总评 = Σ(单科成绩×对应权重),示例代码如下:
Map<String, Double> weights = Map.of("homework", 0.3, "finalExam", 0.7);
double weightedAvg = scores.entrySet().stream()
.mapToDouble(e -> e.getValue() weights.getOrDefault(e.getKey(), 0))
.sum();
Q2: 如何四舍五入到指定小数位?
A: 使用BigDecimal类进行精确控制:
import java.math.BigDecimal;
import java.math.RoundingMode;
...
BigDecimal rawAvg = new BigDecimal(sum).divide(new BigDecimal(count), 2, RoundingMode.HALF_UP);
System.out.println("精确到百分位的平均分:" +
