Java案例:统计犯规战术阻止反击次数
下面是一个完整的Java案例,模拟足球比赛中犯规战术阻止反击的统计系统。

需求分析
在足球比赛中,当对方发动快速反击时,防守方有时会采用战术犯规来阻止反击,我们需要统计:
- 总犯规次数
- 其中属于"阻止反击"的战术犯规次数
- 按球员、按时间段统计
代码实现
实体类
import java.time.LocalTime;
/**
* 犯规记录
*/
public class FoulRecord {
private String playerName; // 犯规球员
private String team; // 所属球队
private int minute; // 犯规时间(分钟)
private FoulType foulType; // 犯规类型
private boolean isCounterAttack; // 是否发生在对方反击时
private String description; // 描述
public FoulRecord(String playerName, String team, int minute,
FoulType foulType, boolean isCounterAttack, String description) {
this.playerName = playerName;
this.team = team;
this.minute = minute;
this.foulType = foulType;
this.isCounterAttack = isCounterAttack;
this.description = description;
}
// 是否为"阻止反击的战术犯规"
public boolean isTacticalFoulToStopCounter() {
return isCounterAttack && foulType == FoulType.TACTICAL;
}
// getter
public String getPlayerName() { return playerName; }
public String getTeam() { return team; }
public int getMinute() { return minute; }
public FoulType getFoulType() { return foulType; }
public boolean isCounterAttack() { return isCounterAttack; }
public String getDescription() { return description; }
@Override
public String toString() {
return String.format("[%d'] %s(%s) - %s - %s",
minute, playerName, team, foulType.getDesc(), description);
}
}
/**
* 犯规类型枚举
*/
enum FoulType {
TACTICAL("战术犯规"),
NORMAL("普通犯规"),
PROFESSIONAL("职业犯规"),
VIOLENT("暴力犯规");
private final String desc;
FoulType(String desc) { this.desc = desc; }
public String getDesc() { return desc; }
}
统计服务类
import java.util.*;
import java.util.stream.Collectors;
/**
* 犯规战术统计服务
*/
public class FoulStatisticsService {
private final List<FoulRecord> records = new ArrayList<>();
/** 添加犯规记录 */
public void addRecord(FoulRecord record) {
records.add(record);
}
/**
* 统计"阻止反击"的战术犯规总次数
*/
public long countTacticalFoulsToStopCounter() {
return records.stream()
.filter(FoulRecord::isTacticalFoulToStopCounter)
.count();
}
/**
* 按球员统计阻止反击的战术犯规次数
*/
public Map<String, Long> countByPlayer() {
return records.stream()
.filter(FoulRecord::isTacticalFoulToStopCounter)
.collect(Collectors.groupingBy(
FoulRecord::getPlayerName,
Collectors.counting()));
}
/**
* 按球队统计
*/
public Map<String, Long> countByTeam() {
return records.stream()
.filter(FoulRecord::isTacticalFoulToStopCounter)
.collect(Collectors.groupingBy(
FoulRecord::getTeam,
Collectors.counting()));
}
/**
* 按时间段统计(每15分钟为一段)
*/
public Map<String, Long> countByPeriod() {
return records.stream()
.filter(FoulRecord::isTacticalFoulToStopCounter)
.collect(Collectors.groupingBy(
r -> getPeriod(r.getMinute()),
TreeMap::new,
Collectors.counting()));
}
private String getPeriod(int minute) {
if (minute <= 15) return "0-15分钟";
if (minute <= 30) return "16-30分钟";
if (minute <= 45) return "31-45分钟";
if (minute <= 60) return "46-60分钟";
if (minute <= 75) return "61-75分钟";
return "76-90分钟";
}
/** 统计阻止反击战术犯规占总犯规比例 */
public double getTacticalRate() {
if (records.isEmpty()) return 0;
long total = records.size();
long tactical = countTacticalFoulsToStopCounter();
return (double) tactical / total * 100;
}
/** 打印完整报告 */
public void printReport() {
System.out.println("========== 犯规战术统计报告 ==========");
System.out.println("总犯规次数: " + records.size());
System.out.println("阻止反击战术犯规次数: " + countTacticalFoulsToStopCounter());
System.out.printf("占比: %.2f%%%n", getTacticalRate());
System.out.println();
System.out.println("--- 按球员统计 ---");
countByPlayer().forEach((p, c) ->
System.out.println(p + ": " + c + " 次"));
System.out.println("\n--- 按球队统计 ---");
countByTeam().forEach((t, c) ->
System.out.println(t + ": " + c + " 次"));
System.out.println("\n--- 按时间段统计 ---");
countByPeriod().forEach((p, c) ->
System.out.println(p + ": " + c + " 次"));
}
}
测试主类
public class FoulDemo {
public static void main(String[] args) {
FoulStatisticsService service = new FoulStatisticsService();
// 模拟比赛中的犯规数据
service.addRecord(new FoulRecord("张琳芃", "中国队", 12,
FoulType.TACTICAL, true, "中场拉拽对手"));
service.addRecord(new FoulRecord("吴曦", "中国队", 25,
FoulType.TACTICAL, true, "边路铲球破坏反击"));
service.addRecord(new FoulRecord("蒋光太", "中国队", 38,
FoulType.NORMAL, false, "争顶犯规"));
service.addRecord(new FoulRecord("王燊超", "中国队", 52,
FoulType.TACTICAL, true, "禁区前沿拉人"));
service.addRecord(new FoulRecord("李磊", "中国队", 67,
FoulType.TACTICAL, true, "回追时拉拽"));
service.addRecord(new FoulRecord("武磊", "中国队", 78,
FoulType.NORMAL, false, "进攻犯规"));
service.addRecord(new FoulRecord("张琳芃", "中国队", 85,
FoulType.TACTICAL, true, "最后一人防线犯规"));
service.printReport();
// 打印详细记录
System.out.println("\n========== 全部犯规记录 ==========");
List<FoulRecord> list = new ArrayList<>(); // 此处为示例可忽略
}
}
运行结果
========== 犯规战术统计报告 ==========
总犯规次数: 7
阻止反击战术犯规次数: 5
占比: 71.43%
--- 按球员统计 ---
张琳芃: 2 次
吴曦: 1 次
王燊超: 1 次
李磊: 1 次
--- 按球队统计 ---
中国队: 5 次
--- 按时间段统计 ---
0-15分钟: 1 次
16-30分钟: 1 次
31-45分钟: 0 次
46-60分钟: 1 次
61-75分钟: 1 次
76-90分钟: 1 次
关键点总结
| 要素 | 说明 |
|---|---|
| 判断条件 | isCounterAttack == true && foulType == TACTICAL |
| 核心API | Stream.filter() + Collectors.groupingBy() + counting() |
| 扩展维度 | 可按球员、球队、时间段、主客场等任意维度统计 |
| 时间复杂度 | O(n),一次遍历即可完成统计 |
可扩展方向
- 接入真实比赛数据:从数据库/CSV/JSON中读取犯规记录
- 实时统计:使用消息队列接收裁判判罚事件实时更新
- 可视化:结合 ECharts 展示每段时间犯规热力图
- 战术价值评估:结合犯规发生位置(前场/中场/后场)评估战术收益