本文目录导读:

我将为您设计一个Java案例来统计足球比赛中的高球传中争顶成功率,这个案例将包含完整的面向对象设计和统计逻辑。
核心实体类设计
// 球员实体类
class Player {
private int id;
private String name;
private String position; // 位置:中锋、后卫等
private double height; // 身高(米)
public Player(int id, String name, String position, double height) {
this.id = id;
this.name = name;
this.position = position;
this.height = height;
}
// Getter和Setter
public int getId() { return id; }
public String getName() { return name; }
public String getPosition() { return position; }
public double getHeight() { return height; }
}
// 争顶事件实体
class AerialDuel {
private int attackerId; // 进攻球员ID
private int defenderId; // 防守球员ID
private boolean isWon; // 是否争顶成功
private String timestamp; // 时间戳
private int gameId; // 比赛ID
public AerialDuel(int attackerId, int defenderId, boolean isWon, String timestamp, int gameId) {
this.attackerId = attackerId;
this.defenderId = defenderId;
this.isWon = isWon;
this.timestamp = timestamp;
this.gameId = gameId;
}
// Getter和Setter
public int getAttackerId() { return attackerId; }
public int getDefenderId() { return defenderId; }
public boolean isWon() { return isWon; }
public String getTimestamp() { return timestamp; }
public int getGameId() { return gameId; }
}
// 比赛实体
class Match {
private int matchId;
private String homeTeam;
private String awayTeam;
private String date;
public Match(int matchId, String homeTeam, String awayTeam, String date) {
this.matchId = matchId;
this.homeTeam = homeTeam;
this.awayTeam = awayTeam;
this.date = date;
}
// Getter方法
public int getMatchId() { return matchId; }
public String getHomeTeam() { return homeTeam; }
public String getAwayTeam() { return awayTeam; }
public String getDate() { return date; }
}
统计服务类
import java.util.*;
import java.util.stream.Collectors;
// 统计服务类
class AerialDuelStatisticsService {
private List<Player> players;
private List<AerialDuel> duels;
private List<Match> matches;
private Map<Integer, String> teamMap; // 球员ID -> 所属球队
public AerialDuelStatisticsService() {
this.players = new ArrayList<>();
this.duels = new ArrayList<>();
this.matches = new ArrayList<>();
this.teamMap = new HashMap<>();
}
// 添加数据方法
public void addPlayer(Player player) {
players.add(player);
}
public void addDuel(AerialDuel duel) {
duels.add(duel);
}
public void addMatch(Match match) {
matches.add(match);
}
public void assignPlayerToTeam(int playerId, String teamName) {
teamMap.put(playerId, teamName);
}
// 计算单个球员的争顶成功率
public double calculatePlayerSuccessRate(int playerId) {
List<AerialDuel> playerDuels = duels.stream()
.filter(d -> isPlayerInDuel(d, playerId))
.collect(Collectors.toList());
if (playerDuels.isEmpty()) {
return 0.0;
}
long wonDuels = playerDuels.stream()
.filter(d -> isPlayerWon(d, playerId))
.count();
return (double) wonDuels / playerDuels.size() * 100;
}
// 判断球员是否参与争顶
private boolean isPlayerInDuel(AerialDuel duel, int playerId) {
return duel.getAttackerId() == playerId || duel.getDefenderId() == playerId;
}
// 判断球员是否赢得争顶
private boolean isPlayerWon(AerialDuel duel, int playerId) {
if (duel.isWon()) {
return duel.getAttackerId() == playerId;
} else {
return duel.getDefenderId() == playerId;
}
}
// 按球队统计争顶成功率
public Map<String, Double> calculateTeamSuccessRate() {
Map<String, List<AerialDuel>> teamDuels = new HashMap<>();
for (AerialDuel duel : duels) {
String attackerTeam = teamMap.get(duel.getAttackerId());
String defenderTeam = teamMap.get(duel.getDefenderId());
teamDuels.computeIfAbsent(attackerTeam, k -> new ArrayList<>()).add(duel);
// 防守方也算争顶
AerialDuel defensiveDuel = new AerialDuel(
duel.getDefenderId(),
duel.getAttackerId(),
!duel.isWon(),
duel.getTimestamp(),
duel.getGameId()
);
teamDuels.computeIfAbsent(defenderTeam, k -> new ArrayList<>()).add(defensiveDuel);
}
Map<String, Double> successRates = new HashMap<>();
for (Map.Entry<String, List<AerialDuel>> entry : teamDuels.entrySet()) {
long wonCount = entry.getValue().stream()
.filter(AerialDuel::isWon)
.count();
double rate = (double) wonCount / entry.getValue().size() * 100;
successRates.put(entry.getKey(), rate);
}
return successRates;
}
// 按位置统计争顶成功率
public Map<String, Double> calculatePositionSuccessRate() {
Map<String, List<AerialDuel>> positionDuels = new HashMap<>();
Map<Integer, Player> playerMap = players.stream()
.collect(Collectors.toMap(Player::getId, p -> p));
for (AerialDuel duel : duels) {
Player attacker = playerMap.get(duel.getAttackerId());
Player defender = playerMap.get(duel.getDefenderId());
if (attacker != null) {
positionDuels.computeIfAbsent(attacker.getPosition() + "-进攻",
k -> new ArrayList<>()).add(duel);
}
if (defender != null) {
positionDuels.computeIfAbsent(defender.getPosition() + "-防守",
k -> new ArrayList<>()).add(new AerialDuel(
duel.getDefenderId(),
duel.getAttackerId(),
!duel.isWon(),
duel.getTimestamp(),
duel.getGameId()
));
}
}
Map<String, Double> successRates = new HashMap<>();
for (Map.Entry<String, List<AerialDuel>> entry : positionDuels.entrySet()) {
long wonCount = entry.getValue().stream()
.filter(AerialDuel::isWon)
.count();
double rate = (double) wonCount / entry.getValue().size() * 100;
successRates.put(entry.getKey(), rate);
}
return successRates;
}
// 按身高分组统计争顶成功率
public Map<String, Double> calculateHeightGroupSuccessRate() {
Map<String, List<AerialDuel>> heightGroups = new LinkedHashMap<>();
Map<Integer, Player> playerMap = players.stream()
.collect(Collectors.toMap(Player::getId, p -> p));
for (AerialDuel duel : duels) {
Player attacker = playerMap.get(duel.getAttackerId());
if (attacker != null) {
String group = getHeightGroup(attacker.getHeight());
heightGroups.computeIfAbsent(group, k -> new ArrayList<>()).add(duel);
}
}
Map<String, Double> successRates = new LinkedHashMap<>();
for (Map.Entry<String, List<AerialDuel>> entry : heightGroups.entrySet()) {
long wonCount = entry.getValue().stream()
.filter(AerialDuel::isWon)
.count();
double rate = (double) wonCount / entry.getValue().size() * 100;
successRates.put(entry.getKey(), rate);
}
return successRates;
}
// 获取身高分组
private String getHeightGroup(double height) {
if (height < 1.75) return "低于1.75m";
if (height < 1.85) return "1.75-1.85m";
if (height < 1.95) return "1.85-1.95m";
return "1.95m以上";
}
// 生成详细报告
public String generateDetailedReport() {
StringBuilder report = new StringBuilder();
report.append("=".repeat(60)).append("\n");
report.append("高球传中争顶成功率统计报告\n");
report.append("=".repeat(60)).append("\n\n");
// 球队统计
report.append("【球队争顶成功率】\n");
Map<String, Double> teamStats = calculateTeamSuccessRate();
teamStats.entrySet().stream()
.sorted(Map.Entry.<String, Double>comparingByValue().reversed())
.forEach(entry -> {
report.append(String.format("%-20s: %.2f%%\n", entry.getKey(), entry.getValue()));
});
// 位置统计
report.append("\n【位置争顶成功率】\n");
Map<String, Double> positionStats = calculatePositionSuccessRate();
positionStats.entrySet().stream()
.sorted(Map.Entry.<String, Double>comparingByValue().reversed())
.forEach(entry -> {
report.append(String.format("%-25s: %.2f%%\n", entry.getKey(), entry.getValue()));
});
// 身高统计
report.append("\n【身高分组争顶成功率】\n");
Map<String, Double> heightStats = calculateHeightGroupSuccessRate();
heightStats.forEach((group, rate) -> {
report.append(String.format("%-15s: %.2f%%\n", group, rate));
});
// 个人排名
report.append("\n【个人争顶成功率排名 TOP 10】\n");
Map<Integer, Double> playerStats = new HashMap<>();
for (Player player : players) {
double rate = calculatePlayerSuccessRate(player.getId());
playerStats.put(player.getId(), rate);
}
playerStats.entrySet().stream()
.sorted(Map.Entry.<Integer, Double>comparingByValue().reversed())
.limit(10)
.forEach(entry -> {
Player player = players.stream()
.filter(p -> p.getId() == entry.getKey())
.findFirst()
.orElse(null);
if (player != null) {
report.append(String.format("%-15s (%s): %.2f%%\n",
player.getName(), player.getPosition(), entry.getValue()));
}
});
return report.toString();
}
}
数据模拟和主程序
import java.util.*;
public class AerialDuelStatisticsSystem {
public static void main(String[] args) {
AerialDuelStatisticsService service = new AerialDuelStatisticsService();
// 模拟球员数据
List<Player> players = generatePlayers();
players.forEach(service::addPlayer);
// 分配球队
Map<String, List<String>> teamPlayers = new HashMap<>();
teamPlayers.put("皇家马德里", Arrays.asList("C罗", "本泽马", "贝尔", "拉莫斯", "马塞洛"));
teamPlayers.put("巴塞罗那", Arrays.asList("梅西", "苏亚雷斯", "格列兹曼", "皮克", "阿尔巴"));
teamPlayers.put("利物浦", Arrays.asList("萨拉赫", "马内", "菲尔米诺", "范戴克", "罗伯逊"));
teamPlayers.put("曼城", Arrays.asList("德布劳内", "热苏斯", "斯特林", "迪亚斯", "坎塞洛"));
// 分配球员到球队
for (Map.Entry<String, List<String>> entry : teamPlayers.entrySet()) {
String team = entry.getKey();
for (String playerName : entry.getValue()) {
Optional<Player> player = players.stream()
.filter(p -> p.getName().equals(playerName))
.findFirst();
player.ifPresent(p -> service.assignPlayerToTeam(p.getId(), team));
}
}
// 生成模拟争顶事件
Random random = new Random(2024);
List<AerialDuel> duels = generateDuelData(players, random);
duels.forEach(service::addDuel);
// 输出统计报告
String report = service.generateDetailedReport();
System.out.println(report);
// 额外展示:特定球员的详细统计
System.out.println("\n" + "=".repeat(60));
System.out.println("个人详细统计示例");
System.out.println("=".repeat(60));
Player samplePlayer = players.get(0); // C罗
double successRate = service.calculatePlayerSuccessRate(samplePlayer.getId());
System.out.printf("%s的争顶成功率为:%.2f%%%n",
samplePlayer.getName(), successRate);
// 统计各球员的争顶次数和成功数
System.out.println("\n【球员争顶统计汇总】");
for (Player player : players) {
double rate = service.calculatePlayerSuccessRate(player.getId());
System.out.printf("%-15s 身高: %.2fm 位置: %-6s 争顶成功率: %.2f%%%n",
player.getName(), player.getHeight(), player.getPosition(), rate);
}
}
// 生成球员数据
private static List<Player> generatePlayers() {
List<Player> players = new ArrayList<>();
// 皇家马德里
players.add(new Player(1, "C罗", "前锋", 1.87));
players.add(new Player(2, "本泽马", "前锋", 1.85));
players.add(new Player(3, "贝尔", "边锋", 1.83));
players.add(new Player(4, "拉莫斯", "后卫", 1.84));
players.add(new Player(5, "马塞洛", "后卫", 1.75));
// 巴塞罗那
players.add(new Player(6, "梅西", "前锋", 1.70));
players.add(new Player(7, "苏亚雷斯", "前锋", 1.82));
players.add(new Player(8, "格列兹曼", "前锋", 1.76));
players.add(new Player(9, "皮克", "后卫", 1.94));
players.add(new Player(10, "阿尔巴", "后卫", 1.68));
// 利物浦
players.add(new Player(11, "萨拉赫", "边锋", 1.75));
players.add(new Player(12, "马内", "边锋", 1.75));
players.add(new Player(13, "菲尔米诺", "前锋", 1.81));
players.add(new Player(14, "范戴克", "后卫", 1.93));
players.add(new Player(15, "罗伯逊", "后卫", 1.78));
// 曼城
players.add(new Player(16, "德布劳内", "中场", 1.81));
players.add(new Player(17, "热苏斯", "前锋", 1.75));
players.add(new Player(18, "斯特林", "边锋", 1.70));
players.add(new Player(19, "迪亚斯", "后卫", 1.87));
players.add(new Player(20, "坎塞洛", "后卫", 1.82));
return players;
}
// 生成模拟争顶事件
private static List<AerialDuel> generateDuelData(List<Player> players, Random random) {
List<AerialDuel> duels = new ArrayList<>();
Map<Integer, String> teamMap = new HashMap<>();
// 球队分配
teamMap.put(1, "皇家马德里"); teamMap.put(2, "皇家马德里");
teamMap.put(3, "皇家马德里"); teamMap.put(4, "皇家马德里");
teamMap.put(5, "皇家马德里");
teamMap.put(6, "巴塞罗那"); teamMap.put(7, "巴塞罗那");
teamMap.put(8, "巴塞罗那"); teamMap.put(9, "巴塞罗那");
teamMap.put(10, "巴塞罗那");
teamMap.put(11, "利物浦"); teamMap.put(12, "利物浦");
teamMap.put(13, "利物浦"); teamMap.put(14, "利物浦");
teamMap.put(15, "利物浦");
teamMap.put(16, "曼城"); teamMap.put(17, "曼城");
teamMap.put(18, "曼城"); teamMap.put(19, "曼城");
teamMap.put(20, "曼城");
// 生成1000次争顶事件
for (int i = 0; i < 1000; i++) {
int attackerId = random.nextInt(20) + 1;
int defenderId;
// 确保防守球员来自不同球队
do {
defenderId = random.nextInt(20) + 1;
} while (teamMap.get(defenderId).equals(teamMap.get(attackerId)));
Player attacker = players.stream()
.filter(p -> p.getId() == attackerId)
.findFirst()
.orElse(null);
Player defender = players.stream()
.filter(p -> p.getId() == defenderId)
.findFirst()
.orElse(null);
// 基于身高差和随机因素计算成功率
double baseRate = 0.5;
if (attacker != null && defender != null) {
double heightAdvantage = (attacker.getHeight() - defender.getHeight()) * 0.2;
baseRate += heightAdvantage;
}
boolean isWon = random.nextDouble() < baseRate;
String timestamp = String.format("%02d:%02d",
random.nextInt(90) + 1, random.nextInt(60));
duels.add(new AerialDuel(attackerId, defenderId, isWon, timestamp, i));
}
return duels;
}
}
高级分析扩展(可选)
// 高级统计分析
class AdvancedAerialAnalysis {
// 趋势分析
public Map<String, Double> analyzeTrend(List<AerialDuel> duels, Player player) {
Map<String, Double> trends = new HashMap<>();
// 按时间段统计
// 按对手强度统计
return trends;
}
// 预测模型(简单线性回归)
public double predictSuccessRate(double height) {
// 基于历史数据的简单预测
return 0.45 + (height - 1.80) * 0.3;
}
}
这个Java案例提供了完整的高球传中争顶成功率统计功能,包括:
- 多维度统计:球队、位置、身高分组
- 个人排名:TOP 10球员
- 详细的报告生成
- 面向对象设计:清晰的数据模型
- 模拟数据:包含真实球员数据进行演示
运行后可以生成详细的统计报告,帮助分析球员和球队的争顶能力。