本文目录导读:

我来帮你写一个Java案例,统计足球比赛中"挑球过人"(挑球过顶/彩虹过人)的次数是否算多,下面是一个完整的示例。
需求分析
假设我们要统计某球员在一场比赛中的技术动作,判断"挑球过人"次数相对其他过人方式是否偏多。
关键点:
- 定义动作类型枚举
- 记录每次动作
- 统计各类过人次数
- 用比例判断"多不多"
代码实现
import java.util.*;
import java.util.stream.Collectors;
/**
* 动作类型枚举
*/
enum ActionType {
NUTMEG("穿裆过人"),
RAINBOW_FLICK("挑球过人"), // 彩虹过人 / 挑球过顶
BODY_FEINT("身体假动作"),
ELASTICO("油炸丸子"),
STEP_OVER("踩单车"),
SHOT("射门"),
PASS("传球");
private final String desc;
ActionType(String desc) { this.desc = desc; }
public String getDesc() { return desc; }
}
/**
* 一次技术动作记录
*/
class ActionRecord {
private final String player;
private final ActionType type;
private final int minute;
public ActionRecord(String player, ActionType type, int minute) {
this.player = player;
this.type = type;
this.minute = minute;
}
public String getPlayer() { return player; }
public ActionType getType() { return type; }
public int getMinute() { return minute; }
@Override
public String toString() {
return String.format("[%2d'] %s - %s", minute, player, type.getDesc());
}
}
public class DribbleStats {
// 判断"多不多"的阈值:挑球过人占所有过人的比例
private static final double HIGH_RATIO = 0.30; // >=30% 认为偏多
public static void main(String[] args) {
// 模拟一场比赛的动作数据
List<ActionRecord> records = Arrays.asList(
new ActionRecord("梅西", ActionType.RAINBOW_FLICK, 12),
new ActionRecord("梅西", ActionType.BODY_FEINT, 18),
new ActionRecord("梅西", ActionType.NUTMEG, 25),
new ActionRecord("梅西", ActionType.RAINBOW_FLICK, 33),
new ActionRecord("梅西", ActionType.STEP_OVER, 40),
new ActionRecord("梅西", ActionType.RAINBOW_FLICK, 55),
new ActionRecord("梅西", ActionType.ELASTICO, 62),
new ActionRecord("梅西", ActionType.RAINBOW_FLICK, 70),
new ActionRecord("梅西", ActionType.PASS, 75),
new ActionRecord("梅西", ActionType.SHOT, 80),
new ActionRecord("梅西", ActionType.RAINBOW_FLICK, 88)
);
// ============ 1. 统计各类动作次数 ============
Map<ActionType, Long> countByType = records.stream()
.collect(Collectors.groupingBy(ActionRecord::getType, Collectors.counting()));
System.out.println("===== 动作统计 =====");
countByType.forEach((type, cnt) ->
System.out.printf("%-8s : %d 次%n", type.getDesc(), cnt));
// ============ 2. 只统计"过人"类动作 ============
Set<ActionType> dribbleTypes = EnumSet.of(
ActionType.NUTMEG,
ActionType.RAINBOW_FLICK,
ActionType.BODY_FEINT,
ActionType.ELASTICO,
ActionType.STEP_OVER
);
long totalDribble = records.stream()
.filter(r -> dribbleTypes.contains(r.getType()))
.count();
long rainbowCount = countByType.getOrDefault(ActionType.RAINBOW_FLICK, 0L);
double ratio = totalDribble == 0 ? 0 : (double) rainbowCount / totalDribble;
// ============ 3. 输出结论 ============
System.out.println("\n===== 挑球过人分析 =====");
System.out.println("总过人次数 : " + totalDribble);
System.out.println("挑球过人次数 : " + rainbowCount);
System.out.printf ("挑球占比 : %.1f%%%n", ratio * 100);
if (ratio >= HIGH_RATIO) {
System.out.println("挑球过人次数偏多 ✅");
} else if (ratio > 0) {
System.out.println("挑球过人次数不多 ❌");
} else {
System.out.println("本场没有使用挑球过人");
}
// ============ 4. 打印明细 ============
System.out.println("\n===== 挑球过人明细 =====");
records.stream()
.filter(r -> r.getType() == ActionType.RAINBOW_FLICK)
.forEach(System.out::println);
}
}
运行结果示例
===== 动作统计 =====
挑球过人 : 5 次
身体假动作 : 1 次
穿裆过人 : 1 次
油炸丸子 : 1 次
踩单车 : 1 次
传球 : 1 次
射门 : 1 次
===== 挑球过人分析 =====
总过人次数 : 9
挑球过人次数 : 5
挑球占比 : 55.6%
挑球过人次数偏多 ✅
===== 挑球过人明细 =====
[12'] 梅西 - 挑球过人
[33'] 梅西 - 挑球过人
[55'] 梅西 - 挑球过人
[70'] 梅西 - 挑球过人
[88'] 梅西 - 挑球过人
关键设计说明
| 模块 | 作用 |
|---|---|
ActionType 枚举 |
统一管理动作类型,避免魔法字符串 |
ActionRecord |
封装一次动作,方便扩展(如加坐标、成功率) |
Set<ActionType> dribbleTypes |
明确"过人"的范围,避免把传球/射门算进去 |
占比阈值 HIGH_RATIO |
判定"多不多"的标准,可按业务调整 |
| Stream 分组统计 | 一行代码完成分类计数 |
可扩展方向
- 多球员对比:加一层
groupingBy(player),对比谁的挑球最多。 - 按时间段统计:
groupingBy(r -> r.getMinute() / 15),看哪个15分钟段爆发。 - 成功率:ActionRecord 增加
success字段,统计挑球成功率。 - 对手维度:加对手字段,判断对谁用挑球效果最好。
- 阈值可配置:改从配置文件读
HIGH_RATIO,方便调整判定标准。
如果你想要的是具体的真实足球数据(比如某球员某场比赛挑球次数),那需要接入数据源(如 Opta、StatsBomb、SofaScore),Java 侧用 HTTP 客户端拉取 JSON 再解析即可,需要的话我也可以给你写一个拉取JSON并解析的版本。