java案例统计门前抢点射门次数对比?

wen java案例 1

Java 案例:统计门前抢点射门次数对比

下面通过一个完整的 Java 案例,演示如何统计两名前锋"门前抢点"射门次数并进行对比,案例涵盖枚举、实体类、Stream 流统计、Comparator 排序、格式化输出等知识点。

java案例统计门前抢点射门次数对比?


需求说明

  • 模拟一场足球比赛中两名前锋的射门记录
  • 筛选出射门类型为"门前抢点"的记录
  • 统计两人门前抢点射门次数并对比
  • 输出对比结果(谁更多、差值、占比)

完整代码

import java.util.*;
import java.util.stream.Collectors;
// 1. 射门类型枚举
enum ShotType {
    CLOSE_RANGE("门前抢点"),
    LONG_SHOT("远射"),
    HEADER("头球"),
    PENALTY("点球"),
    FREE_KICK("任意球");
    private final String desc;
    ShotType(String desc) { this.desc = desc; }
    public String getDesc() { return desc; }
}
// 2. 射门记录实体
class ShotRecord {
    private String playerName;   // 球员名
    private ShotType type;       // 射门类型
    private int minute;          // 比赛分钟
    private boolean onTarget;    // 是否射正
    public ShotRecord(String playerName, ShotType type, int minute, boolean onTarget) {
        this.playerName = playerName;
        this.type = type;
        this.minute = minute;
        this.onTarget = onTarget;
    }
    public String getPlayerName() { return playerName; }
    public ShotType getType()     { return type; }
    public int getMinute()        { return minute; }
    public boolean isOnTarget()   { return onTarget; }
    @Override
    public String toString() {
        return String.format("%s 第%d分钟 %s%s",
                playerName, minute, type.getDesc(), onTarget ? "(射正)" : "(射偏)");
    }
}
// 3. 主程序
public class CloseRangeShotStats {
    public static void main(String[] args) {
        // 模拟射门数据
        List<ShotRecord> shots = Arrays.asList(
                new ShotRecord("张三", ShotType.CLOSE_RANGE, 12, true),
                new ShotRecord("张三", ShotType.LONG_SHOT,   25, false),
                new ShotRecord("张三", ShotType.CLOSE_RANGE, 38, true),
                new ShotRecord("张三", ShotType.CLOSE_RANGE, 55, false),
                new ShotRecord("张三", ShotType.HEADER,      70, true),
                new ShotRecord("李四", ShotType.CLOSE_RANGE, 18, true),
                new ShotRecord("李四", ShotType.CLOSE_RANGE, 33, true),
                new ShotRecord("李四", ShotType.CLOSE_RANGE, 60, true),
                new ShotRecord("李四", ShotType.CLOSE_RANGE, 82, false),
                new ShotRecord("李四", ShotType.PENALTY,     45, true),
                new ShotRecord("李四", ShotType.FREE_KICK,   88, false)
        );
        System.out.println("========== 全部射门记录 ==========");
        shots.forEach(System.out::println);
        // 4. 筛选"门前抢点"记录并按球员统计
        Map<String, Long> closeRangeCount = shots.stream()
                .filter(s -> s.getType() == ShotType.CLOSE_RANGE)
                .collect(Collectors.groupingBy(
                        ShotRecord::getPlayerName,
                        Collectors.counting()
                ));
        System.out.println("\n========== 门前抢点次数统计 ==========");
        closeRangeCount.forEach((player, count) ->
                System.out.printf("%s:%d 次%n", player, count));
        // 5. 对比(按次数降序)
        List<Map.Entry<String, Long>> ranking = closeRangeCount.entrySet().stream()
                .sorted(Map.Entry.<String, Long>comparingByValue().reversed())
                .collect(Collectors.toList());
        System.out.println("\n========== 对比结果 ==========");
        if (ranking.size() >= 2) {
            Map.Entry<String, Long> first  = ranking.get(0);
            Map.Entry<String, Long> second = ranking.get(1);
            long diff = first.getValue() - second.getValue();
            double total = first.getValue() + second.getValue();
            double ratio = total == 0 ? 0 : first.getValue() * 100.0 / total;
            System.out.printf("🥇 %s:%d 次%n", first.getKey(),  first.getValue());
            System.out.printf("🥈 %s:%d 次%n", second.getKey(), second.getValue());
            System.out.printf("次数差:%d 次%n", diff);
            System.out.printf("%s 门前抢点占比:%.2f%%%n", first.getKey(), ratio);
            if (diff == 0) {
                System.out.println("两人门前抢点能力不分伯仲!");
            } else {
                System.out.printf("%s 门前抢点次数多 %d 次,抢点意识更强。%n",
                        first.getKey(), diff);
            }
        }
        // 6. 附加:门前抢点射正率对比
        System.out.println("\n========== 门前抢点射正率对比 ==========");
        Map<String, List<ShotRecord>> grouped = shots.stream()
                .filter(s -> s.getType() == ShotType.CLOSE_RANGE)
                .collect(Collectors.groupingBy(ShotRecord::getPlayerName));
        grouped.forEach((player, list) -> {
            long onTarget = list.stream().filter(ShotRecord::isOnTarget).count();
            double rate = list.isEmpty() ? 0 : onTarget * 100.0 / list.size();
            System.out.printf("%s:射门 %d 次,射正 %d 次,射正率 %.2f%%%n",
                    player, list.size(), onTarget, rate);
        });
    }
}

运行结果

========== 全部射门记录 ==========
张三 第12分钟 门前抢点(射正)
张三 第25分钟 远射(射偏)
张三 第38分钟 门前抢点(射正)
张三 第55分钟 门前抢点(射偏)
张三 第70分钟 头球(射正)
李四 第18分钟 门前抢点(射正)
李四 第33分钟 门前抢点(射正)
李四 第60分钟 门前抢点(射正)
李四 第82分钟 门前抢点(射偏)
李四 第45分钟 点球(射正)
李四 第88分钟 任意球(射偏)
========== 门前抢点次数统计 ==========
张三:3 次
李四:4 次
========== 对比结果 ==========
🥇 李四:4 次
🥈 张三:3 次
次数差:1 次
李四 门前抢点占比:57.14%
李四 门前抢点次数多 1 次,抢点意识更强。
========== 门前抢点射正率对比 ==========
张三:射门 3 次,射正 2 次,射正率 66.67%
李四:射门 4 次,射正 3 次,射正率 75.00%

核心知识点解析

技术点 说明
枚举 ShotType 用枚举代替字符串表示射门类型,避免魔法值,便于扩展
filter 过滤出 type == CLOSE_RANGE 的记录
Collectors.groupingBy 按球员分组,便于分人统计
Collectors.counting() 作为下游收集器,统计每组记录数
comparingByValue().reversed() 按次数降序排序,得到排名
Map.Entry 遍历 Map 键值对,取第一名/第二名进行对比
附加射正率 再次分组并 filter(isOnTarget) 计算命中率,扩展对比维度

扩展思路

  1. 多轮比赛累积:把 shots 换成从数据库/文件读取的 List,可统计联赛整个赛季。
  2. 加入队伍维度:在 ShotRecord 中加 team 字段,groupingBy(team → player) 多级分组。
  3. 图表输出:统计结果导出为 CSV,用 Excel/Python 画柱状图对比。
  4. 自定义对比指标:可把"次数"换成"预期进球(xG)""转化率"等指标,只需改 counting() 为 summingDouble。

如果需要,我可以把上面的例子改成 多级分组(球队 → 球员)+ 输出到文件 的版本。

友情链接

欧易欧易欧易欧易欧易欧易欧易欧易直播帮篮球控NBA帮比赛虎聊足球

上一篇根据java案例,赔率波动暗示了什么?

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

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

友情链接攻略窝 · 礼包窝 · 配置窝 · 换算窝 · 算法窝 · 查文窝 · 手册窝 · 问答窝 · 全文搜 · 手册库
相关站点礼包窝 · 查文窝