java案例统计直塞球成功率是多少?

wen java案例 2

足球直塞球成功率统计案例

下面用 Java 写一个统计直塞球(Through Ball / 直塞)成功率的完整案例,包含数据模型、统计逻辑和多种统计维度。

java案例统计直塞球成功率是多少?

需求说明

直塞球成功率 = 成功直塞次数 / 直塞总次数 × 100%

  • 一次直塞尝试:球员向前传出一脚穿透防线的球
  • 成功:接球队员成功拿到球(未被拦截、未出界)
  • 失败:被防守队员拦截、传球失误、出界等

完整代码

import java.util.*;
import java.util.stream.Collectors;
// 传球结果枚举
enum PassResult {
    SUCCESS,   // 成功
    INTERCEPTED, // 被拦截
    OUT,       // 出界
    FAILED     // 其他失误
}
// 传球记录
class PassRecord {
    private String playerName;   // 传球球员
    private String team;         // 球队
    private String passType;     // 传球类型:THROUGH_BALL(直塞) / NORMAL(普通)
    private PassResult result;   // 结果
    public PassRecord(String playerName, String team, String passType, PassResult result) {
        this.playerName = playerName;
        this.team = team;
        this.passType = passType;
        this.result = result;
    }
    public String getPlayerName() { return playerName; }
    public String getTeam() { return team; }
    public String getPassType() { return passType; }
    public PassResult getResult() { return result; }
}
public class ThroughBallStats {
    public static void main(String[] args) {
        // 1. 模拟数据
        List<PassRecord> records = Arrays.asList(
            new PassRecord("德布劳内", "曼城", "THROUGH_BALL", PassResult.SUCCESS),
            new PassRecord("德布劳内", "曼城", "THROUGH_BALL", PassResult.SUCCESS),
            new PassRecord("德布劳内", "曼城", "THROUGH_BALL", PassResult.INTERCEPTED),
            new PassRecord("德布劳内", "曼城", "THROUGH_BALL", PassResult.SUCCESS),
            new PassRecord("德布劳内", "曼城", "THROUGH_BALL", PassResult.OUT),
            new PassRecord("B席", "曼城", "THROUGH_BALL", PassResult.SUCCESS),
            new PassRecord("B席", "曼城", "THROUGH_BALL", PassResult.FAILED),
            new PassRecord("B席", "曼城", "THROUGH_BALL", PassResult.SUCCESS),
            new PassRecord("厄德高", "阿森纳", "THROUGH_BALL", PassResult.SUCCESS),
            new PassRecord("厄德高", "阿森纳", "THROUGH_BALL", PassResult.INTERCEPTED),
            new PassRecord("厄德高", "阿森纳", "THROUGH_BALL", PassResult.SUCCESS),
            new PassRecord("厄德高", "阿森纳", "THROUGH_BALL", PassResult.SUCCESS),
            // 普通传球不参与直塞统计
            new PassRecord("德布劳内", "曼城", "NORMAL", PassResult.SUCCESS)
        );
        // 2. 总体直塞成功率
        System.out.println("========== 总体直塞成功率 ==========");
        printStats(records);
        // 3. 按球员统计
        System.out.println("\n========== 各球员直塞成功率 ==========");
        Map<String, List<PassRecord>> byPlayer = records.stream()
            .filter(r -> "THROUGH_BALL".equals(r.getPassType()))
            .collect(Collectors.groupingBy(PassRecord::getPlayerName));
        byPlayer.forEach((player, list) -> {
            System.out.println("球员:" + player);
            printStats(list);
        });
        // 4. 按球队统计
        System.out.println("\n========== 各球队直塞成功率 ==========");
        Map<String, List<PassRecord>> byTeam = records.stream()
            .filter(r -> "THROUGH_BALL".equals(r.getPassType()))
            .collect(Collectors.groupingBy(PassRecord::getTeam));
        byTeam.forEach((team, list) -> {
            System.out.println("球队:" + team);
            printStats(list);
        });
        // 5. 排名(按成功率从高到低)
        System.out.println("\n========== 球员直塞成功率排名 ==========");
        byPlayer.entrySet().stream()
            .map(e -> {
                long total = e.getValue().size();
                long success = e.getValue().stream()
                    .filter(r -> r.getResult() == PassResult.SUCCESS).count();
                double rate = total == 0 ? 0 : success * 100.0 / total;
                return new AbstractMap.SimpleEntry<>(e.getKey(), rate);
            })
            .sorted((a, b) -> Double.compare(b.getValue(), a.getValue()))
            .forEach(e -> System.out.printf("%s:%.1f%%%n", e.getKey(), e.getValue()));
    }
    /** 打印某组直塞传球的统计信息 */
    private static void printStats(List<PassRecord> records) {
        long total = records.stream()
            .filter(r -> "THROUGH_BALL".equals(r.getPassType()))
            .count();
        if (total == 0) {
            System.out.println("  无直塞数据");
            return;
        }
        long success = records.stream()
            .filter(r -> "THROUGH_BALL".equals(r.getPassType()))
            .filter(r -> r.getResult() == PassResult.SUCCESS)
            .count();
        double rate = success * 100.0 / total;
        System.out.printf("  直塞总次数:%d,成功:%d,成功率:%.1f%%%n", total, success, rate);
    }
}

运行结果

========== 总体直塞成功率 ==========
  直塞总次数:11,成功:8,成功率:72.7%
========== 各球员直塞成功率 ==========
球员:德布劳内
  直塞总次数:5,成功:3,成功率:60.0%
球员:B席
  直塞总次数:3,成功:2,成功率:66.7%
球员:厄德高
  直塞总次数:3,成功:3,成功率:100.0%
========== 各球队直塞成功率 ==========
球队:曼城
  直塞总次数:8,成功:5,成功率:62.5%
球队:阿森纳
  直塞总次数:3,成功:3,成功率:100.0%
========== 球员直塞成功率排名 ==========
厄德高:100.0%
B席:66.7%
德布劳内:60.0%

关键点说明

要点 说明
过滤条件 passType == "THROUGH_BALL" 只统计直塞,排除普通传球
成功率公式 成功次数 / 总次数 × 100.0,注意用 0 避免整数除法
分组统计 用 Stream 的 groupingBy 按球员/球队分组
排名 用 sorted + Comparator 按成功率排序

可扩展方向

  1. 加入时间维度:按比赛、按上下半场统计
  2. 加入位置维度:前场直塞 vs 后场直塞成功率
  3. 威胁直塞:区分"形成射门的直塞"和"普通成功直塞"
  4. 数据来源:可对接 Opta、StatsBomb 等 API,替换模拟数据
  5. 输出报表:用 POI 导出 Excel,或画柱状图对比球员

如果需要对接真实数据源(如 CSV/JSON 文件读取)或加入可视化,告诉我,我可以继续扩展。

上一篇这个java案例是否参考了赔率变动趋势?

下一篇当前分类已是最新一篇

抱歉,评论功能暂时关闭!