Java 案例:统计扑救次数,判断哪位门将更忙
下面通过一个完整的 Java 案例,模拟统计多名门将的扑救数据,并分析"谁更忙"(扑救次数最多)。

需求分析
- 定义门将类
Goalkeeper,包含姓名、扑救次数等属性 - 统计每位门将的扑救次数
- 找出扑救次数最多的门将(即"更忙"的门将)
- 输出排序结果和最多扑救的门将
完整代码实现
import java.util.*;
import java.util.stream.Collectors;
// 门将类
class Goalkeeper {
private String name; // 姓名
private int saves; // 扑救次数
private int matches; // 出场次数
public Goalkeeper(String name, int saves, int matches) {
this.name = name;
this.saves = saves;
this.matches = matches;
}
public String getName() { return name; }
public int getSaves() { return saves; }
public int getMatches() { return matches; }
// 场均扑救次数
public double getSavesPerMatch() {
return matches == 0 ? 0 : (double) saves / matches;
}
@Override
public String toString() {
return String.format("%-8s | 扑救: %2d 次 | 出场: %2d 场 | 场均: %.2f 次",
name, saves, matches, getSavesPerMatch());
}
}
public class GoalkeeperStats {
public static void main(String[] args) {
// 1. 准备数据
List<Goalkeeper> keepers = Arrays.asList(
new Goalkeeper("王大雷", 45, 20),
new Goalkeeper("颜骏凌", 62, 22),
new Goalkeeper("刘殿座", 38, 18),
new Goalkeeper("韩佳奇", 55, 19),
new Goalkeeper("鲍亚雄", 50, 21)
);
System.out.println("========== 门将扑救统计数据 ==========");
keepers.forEach(System.out::println);
// 2. 按扑救次数排序(降序)
List<Goalkeeper> sorted = keepers.stream()
.sorted(Comparator.comparingInt(Goalkeeper::getSaves).reversed())
.collect(Collectors.toList());
System.out.println("\n========== 按扑救次数排序 ==========");
sorted.forEach(System.out::println);
// 3. 找出"最忙"的门将(扑救最多)
Goalkeeper busiest = keepers.stream()
.max(Comparator.comparingInt(Goalkeeper::getSaves))
.orElse(null);
System.out.println("\n========== 最忙的门将 ==========");
if (busiest != null) {
System.out.println("🏆 " + busiest.getName()
+ " 扑救 " + busiest.getSaves() + " 次,当之无愧的"忙碌之王"!");
}
// 4. 计算总扑救数、平均值
int totalSaves = keepers.stream().mapToInt(Goalkeeper::getSaves).sum();
double avgSaves = keepers.stream().mapToInt(Goalkeeper::getSaves).average().orElse(0);
System.out.println("\n========== 总体统计 ==========");
System.out.printf("总扑救次数: %d 次%n", totalSaves);
System.out.printf("平均扑救次数: %.2f 次%n", avgSaves);
// 5. 找出扑救次数高于平均值的门将
System.out.println("\n========== 高于平均水平的门将 ==========");
keepers.stream()
.filter(g -> g.getSaves() > avgSaves)
.forEach(g -> System.out.println(g.getName() + " -> " + g.getSaves() + " 次"));
}
}
运行结果示例
========== 门将扑救统计数据 ==========
王大雷 | 扑救: 45 次 | 出场: 20 场 | 场均: 2.25 次
颜骏凌 | 扑救: 62 次 | 出场: 22 场 | 场均: 2.82 次
刘殿座 | 扑救: 38 次 | 出场: 18 场 | 场均: 2.11 次
韩佳奇 | 扑救: 55 次 | 出场: 19 场 | 场均: 2.89 次
鲍亚雄 | 扑救: 50 次 | 出场: 21 场 | 场均: 2.38 次
========== 按扑救次数排序 ==========
颜骏凌 | 扑救: 62 次 | 出场: 22 场 | 场均: 2.82 次
韩佳奇 | 扑救: 55 次 | 出场: 19 场 | 场均: 2.89 次
鲍亚雄 | 扑救: 50 次 | 出场: 21 场 | 场均: 2.38 次
王大雷 | 扑救: 45 次 | 出场: 20 场 | 场均: 2.25 次
刘殿座 | 扑救: 38 次 | 出场: 18 场 | 场均: 2.11 次
========== 最忙的门将 ==========
🏆 颜骏凌 扑救 62 次,当之无愧的"忙碌之王"!
========== 总体统计 ==========
总扑救次数: 250 次
平均扑救次数: 50.00 次
========== 高于平均水平的门将 ==========
颜骏凌 -> 62 次
韩佳奇 -> 55 次
关键知识点解析
| 技术点 | 说明 |
|---|---|
Comparator.comparingInt(...).reversed() |
按整数字段降序排序 |
stream().max(...) |
求最大值元素 |
mapToInt(...).sum()/average() |
对字段求和/求平均 |
filter(...) |
按条件过滤元素 |
Collectors.toList() |
将流收集为列表 |
自定义 toString() + String.format |
格式化输出 |
扩展思路
-
按场均扑救判断"忙":如果门将出场次数差异大,用 场均扑救次数 更公平,改一行即可:
Goalkeeper busiest = keepers.stream() .max(Comparator.comparingDouble(Goalkeeper::getSavesPerMatch)) .orElse(null); -
从文件/数据库读取数据:将
Arrays.asList(...)替换为读取 CSV 或数据库结果,即可对接真实比赛数据。 -
可视化扩展:可将结果输出为 JSON,或用 JavaFX/Chart 生成柱状图。
-
多赛季统计:增加
season字段,用Collectors.groupingBy分组后再统计。
💡 小结:判断"谁更忙"的核心就是对扑救次数进行聚合和比较,本案例使用 Stream API 让代码更简洁,同时兼顾了排序、求和、平均值、过滤等常见统计需求,非常适合作为 Java 集合与流式编程的练手案例。