Java 案例:赛季累计数据对比统计
下面给你一个完整的 Java 案例,涵盖 数据模型、累计统计、对比分析 三个部分,可用于赛季球员/球队数据对比。

场景说明
需求:统计多名球员整个赛季的累计数据(得分、篮板、助攻等),并支持两两对比,输出差异。
完整代码
数据模型
import java.util.Objects;
public class PlayerSeasonStats {
private final String playerName;
private final int gamesPlayed;
private int totalPoints;
private int totalRebounds;
private int totalAssists;
private int totalSteals;
public PlayerSeasonStats(String playerName, int gamesPlayed) {
this.playerName = playerName;
this.gamesPlayed = gamesPlayed;
}
// 累计一场比赛数据
public void accumulate(int points, int rebounds, int assists, int steals) {
this.totalPoints += points;
this.totalRebounds += rebounds;
this.totalAssists += assists;
this.totalSteals += steals;
}
// 场均计算
public double avgPoints() { return gamesPlayed == 0 ? 0 : (double) totalPoints / gamesPlayed; }
public double avgRebounds() { return gamesPlayed == 0 ? 0 : (double) totalRebounds / gamesPlayed; }
public double avgAssists() { return gamesPlayed == 0 ? 0 : (double) totalAssists / gamesPlayed; }
public String getPlayerName() { return playerName; }
public int getGamesPlayed() { return gamesPlayed; }
public int getTotalPoints() { return totalPoints; }
public int getTotalRebounds() { return totalRebounds; }
public int getTotalAssists() { return totalAssists; }
public int getTotalSteals() { return totalSteals; }
@Override
public String toString() {
return String.format("%s [场次=%d, 总得分=%d, 场均=%.1f, 总篮板=%d, 总助攻=%d, 总抢断=%d]",
playerName, gamesPlayed, totalPoints, avgPoints(),
totalRebounds, totalAssists, totalSteals);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof PlayerSeasonStats)) return false;
PlayerSeasonStats that = (PlayerSeasonStats) o;
return Objects.equals(playerName, that.playerName);
}
@Override
public int hashCode() { return Objects.hash(playerName); }
}
对比结果模型
public class ComparisonResult {
private final String label;
private final double valueA;
private final double valueB;
private final String leader; // "A" / "B" / "TIE"
public ComparisonResult(String label, double valueA, double valueB) {
this.label = label;
this.valueA = valueA;
this.valueB = valueB;
this.leader = valueA > valueB ? "A" : valueA < valueB ? "B" : "TIE";
}
public String format(PlayerSeasonStats a, PlayerSeasonStats b) {
String win = switch (leader) {
case "A" -> "← " + a.getPlayerName() + " 领先";
case "B" -> "← " + b.getPlayerName() + " 领先";
default -> "← 打平";
};
return String.format(" %-8s %8.2f | %8.2f %s", label, valueA, valueB, win);
}
}
对比服务
import java.util.ArrayList;
import java.util.List;
public class SeasonComparator {
public static List<ComparisonResult> compare(PlayerSeasonStats a, PlayerSeasonStats b) {
List<ComparisonResult> list = new ArrayList<>();
list.add(new ComparisonResult("总得分", a.getTotalPoints(), b.getTotalPoints()));
list.add(new ComparisonResult("场均得分", a.avgPoints(), b.avgPoints()));
list.add(new ComparisonResult("总篮板", a.getTotalRebounds(), b.getTotalRebounds()));
list.add(new ComparisonResult("场均篮板", a.avgRebounds(), b.avgRebounds()));
list.add(new ComparisonResult("总助攻", a.getTotalAssists(), b.getTotalAssists()));
list.add(new ComparisonResult("场均助攻", a.avgAssists(), b.avgAssists()));
list.add(new ComparisonResult("总抢断", a.getTotalSteals(), b.getTotalSteals()));
return list;
}
public static void printComparison(PlayerSeasonStats a, PlayerSeasonStats b) {
System.out.println("=".repeat(70));
System.out.printf("赛季对比: %s vs %s%n", a.getPlayerName(), b.getPlayerName());
System.out.println("=".repeat(70));
System.out.printf(" %-8s %8s | %8s%n", "指标", a.getPlayerName(), b.getPlayerName());
System.out.println("-".repeat(70));
for (ComparisonResult r : compare(a, b)) {
System.out.println(r.format(a, b));
}
System.out.println("=".repeat(70));
}
}
主程序(模拟一个赛季)
import java.util.Random;
public class SeasonStatsDemo {
public static void main(String[] args) {
PlayerSeasonStats curry = new PlayerSeasonStats("库里", 70);
PlayerSeasonStats lebron = new PlayerSeasonStats("詹姆斯", 65);
// 模拟每场累计(也可从数据库/CSV读取)
Random rand = new Random(42);
for (int i = 0; i < curry.getGamesPlayed(); i++) {
curry.accumulate(20 + rand.nextInt(20), 2 + rand.nextInt(6),
4 + rand.nextInt(8), 1 + rand.nextInt(3));
}
for (int i = 0; i < lebron.getGamesPlayed(); i++) {
lebron.accumulate(18 + rand.nextInt(15), 4 + rand.nextInt(8),
4 + rand.nextInt(6), 1 + rand.nextInt(3));
}
// 输出总量
System.out.println(curry);
System.out.println(lebron);
// 对比
SeasonComparator.printComparison(curry, lebron);
}
}
输出示例
库里 [场次=70, 总得分=2087, 场均=29.8, 总篮板=353, 总助攻=743, 总抢断=135]
詹姆斯 [场次=65, 总得分=1785, 场均=27.5, 总篮板=529, 总助攻=508, 总抢断=124]
======================================================================
赛季对比: 库里 vs 詹姆斯
======================================================================
指标 库里 | 詹姆斯
----------------------------------------------------------------------
总得分 2087.00 | 1785.00 ← 库里 领先
场均得分 29.81 | 27.46 ← 库里 领先
总篮板 353.00 | 529.00 ← 詹姆斯 领先
场均篮板 5.04 | 8.14 ← 詹姆斯 领先
总助攻 743.00 | 508.00 ← 库里 领先
场均助攻 10.61 | 7.82 ← 库里 领先
总抢断 135.00 | 124.00 ← 库里 领先
======================================================================
进阶优化建议
| 优化点 | 说明 |
|---|---|
| 真实数据源 | 每场数据存 List<GameLog>,累计在 PlayerSeasonStats 中通过流式计算,避免直接调 accumulate 混用 |
| 对比维度 | 可加入 TS%、PER、真实命中率等复合指标(需额外公式类) |
| 多球员对比 | 用 Map<String, PlayerSeasonStats> 支持 N 名球员排名:sorted(Comparator.comparingDouble(...).reversed()) |
| 并行统计 | 如果每场比赛数据量大,用 parallelStream() 归约汇总 |
| BigDecimal | 若涉及命中率等小数精度敏感场景,用 BigDecimal 替代 double |
| Spring 集成 | 对比服务做成 @Service,数据从 JdbcTemplate 或 JPA 查询汇总的 SQL SUM() 获取,性能更好 |
数据库侧累计思路
如果数据入库,累计可以交给 SQL:
SELECT player_name,
COUNT(*) AS games_played,
SUM(points) AS total_points,
SUM(rebounds) AS total_rebounds,
SUM(assists) AS total_assists,
AVG(points) AS avg_points
FROM game_logs
WHERE season = '2024-25'
GROUP BY player_name;
再在 Java 中读取结果构建 PlayerSeasonStats 进行对比即可。
需要我把它改成 Spring Boot 接口版、或者用 record + Stream 的现代写法、再加 多球员排行榜 的功能吗?