Java 案例:点球命中率对比分析
下面通过一个完整的 Java 案例,模拟并对比不同球员/球队的点球命中率,包含数据模型、统计计算、对比分析和可视化输出。

场景设计
模拟一场点球对比分析,比较 4 名球员的点球表现:
| 球员 | 主罚次数 | 命中次数 |
|---|---|---|
| 梅西 | 20 | 16 |
| C罗 | 25 | 21 |
| 内马尔 | 18 | 13 |
| 姆巴佩 | 22 | 19 |
完整代码
import java.util.*;
import java.util.stream.*;
// 1. 球员点球数据模型
class PlayerPenalty {
private String name;
private int totalShots; // 主罚次数
private int goals; // 命中次数
public PlayerPenalty(String name, int totalShots, int goals) {
this.name = name;
this.totalShots = totalShots;
this.goals = goals;
}
public String getName() { return name; }
public int getTotalShots() { return totalShots; }
public int getGoals() { return goals; }
// 命中率(百分比)
public double getHitRate() {
return totalShots == 0 ? 0 : (double) goals / totalShots * 100;
}
@Override
public String toString() {
return String.format("%-6s 主罚:%2d 命中:%2d 命中率:%.2f%%",
name, totalShots, goals, getHitRate());
}
}
// 2. 对比分析主类
public class PenaltyAnalysis {
public static void main(String[] args) {
List<PlayerPenalty> players = Arrays.asList(
new PlayerPenalty("梅西", 20, 16),
new PlayerPenalty("C罗", 25, 21),
new PlayerPenalty("内马尔", 18, 13),
new PlayerPenalty("姆巴佩", 22, 19)
);
System.out.println("========== 点球命中率对比 ==========");
players.forEach(System.out::println);
// 3. 按命中率排序
System.out.println("\n========== 命中率排名(从高到低)==========");
List<PlayerPenalty> ranked = players.stream()
.sorted(Comparator.comparingDouble(PlayerPenalty::getHitRate).reversed())
.collect(Collectors.toList());
int rank = 1;
for (PlayerPenalty p : ranked) {
System.out.printf("第%d名: %s%n", rank++, p);
}
// 4. 找出命中率最高和最低
PlayerPenalty best = ranked.get(0);
PlayerPenalty worst = ranked.get(ranked.size() - 1);
System.out.println("\n最高命中率: " + best.getName() + " (" + String.format("%.2f%%", best.getHitRate()) + ")");
System.out.println("最低命中率: " + worst.getName() + " (" + String.format("%.2f%%", worst.getHitRate()) + ")");
// 5. 全队整体命中率
int totalShots = players.stream().mapToInt(PlayerPenalty::getTotalShots).sum();
int totalGoals = players.stream().mapToInt(PlayerPenalty::getGoals).sum();
double overallRate = (double) totalGoals / totalShots * 100;
System.out.printf("\n全队整体命中率: %d/%d = %.2f%%%n", totalGoals, totalShots, overallRate);
// 6. 高于平均命中率的球员
double avgRate = players.stream().mapToDouble(PlayerPenalty::getHitRate).average().orElse(0);
System.out.printf("\n平均命中率: %.2f%%%n", avgRate);
System.out.println("高于平均水平的球员:");
players.stream()
.filter(p -> p.getHitRate() > avgRate)
.forEach(p -> System.out.println(" ✔ " + p.getName()));
// 7. 简易可视化(柱状图)
System.out.println("\n========== 命中率可视化 ==========");
for (PlayerPenalty p : ranked) {
int bars = (int) Math.round(p.getHitRate() / 5); // 每 5% 一个方块
System.out.printf("%-6s |%s %.2f%%%n",
p.getName(),
"█".repeat(bars),
p.getHitRate());
}
}
}
运行结果
========== 点球命中率对比 ==========
梅西 主罚:20 命中:16 命中率:80.00%
C罗 主罚:25 命中:21 命中率:84.00%
内马尔 主罚:18 命中:13 命中率:72.22%
姆巴佩 主罚:22 命中:19 命中率:86.36%
========== 命中率排名(从高到低)==========
第1名: 姆巴佩 主罚:22 命中:19 命中率:86.36%
第2名: C罗 主罚:25 命中:21 命中率:84.00%
第3名: 梅西 主罚:20 命中:16 命中率:80.00%
第4名: 内马尔 主罚:18 命中:13 命中率:72.22%
最高命中率: 姆巴佩 (86.36%)
最低命中率: 内马尔 (72.22%)
全队整体命中率: 69/85 = 81.18%
平均命中率: 80.65%
高于平均水平的球员:
✔ 姆巴佩
✔ C罗
========== 命中率可视化 ==========
姆巴佩 |█████████████████ 86.36%
C罗 |█████████████████ 84.00%
梅西 |████████████████ 80.00%
内马尔 |██████████████ 72.22%
- 姆巴佩命中率最高(86.36%),虽然主罚次数不是最多,但效率最高。
- C罗命中率 84%,且样本量最大(25 次),稳定性最好,含金量高。
- 梅西 80% 略低于平均线(80.65%),表现中规中矩。
- 内马尔 72.22% 最低,明显低于平均水平,是短板。
- 全队整体命中率 81.18%,且只有 2 人高于平均线,说明个体差异明显。
关键设计点
| 要点 | 说明 |
|---|---|
| 命中率计算 | goals / totalShots × 100,用 double 避免整数除法丢失精度 |
| 空数据保护 | totalShots == 0 时返回 0,防止除零异常 |
| Stream 排序 | Comparator.comparingDouble(...).reversed() 简洁实现排名 |
| 平均值/求和 | mapToDouble().average() / mapToInt().sum() 聚合统计 |
| 可视化 | 用 字符按比例画出柱状图,纯控制台实现 |
这样既完成了hit rate 的精确对比,又给出了排名、极值、平均线、整体水平和图形化的多维度分析,是一个可直接运行的完整 Java 案例。